在上一篇中,我們基本簡單搭建了一個工程。如上文所說,ember-cli外掛程式,是基於broccoli.js 來進行資源管理以及目錄結構管理的,所以說,瞭解目錄結構對我們來說有很重要的意義,此外我們還是說道一些常用的配置。 ember工程目錄結構
在使用ember new <project-name>的時候,會將你的目錄結構打出來,如下:
簡單來說,如下所示,其中比較重要(或者說需要修改)的檔案,用紅色標出:
這裡著重介紹2個檔案
environment.js以及ember-cli-build.js
以及順帶說一下.jshintrc,route.js environment.js
這個檔案,顧名思義,主要用來配置和環境相關的內容,初始內容如下:
/* jshint node: true */module.exports = function(environment) { var ENV = { modulePrefix: 'ember-demo', environment: environment, rootURL: '/', locationType: 'auto', EmberENV: { FEATURES: { } }, APP: { } }; if (environment === 'development') { } if (environment === 'test') { // Testem prefers this... ENV.locationType = 'none'; // keep test console output quieter ENV.APP.LOG_ACTIVE_GENERATION = false; ENV.APP.LOG_VIEW_LOOKUPS = false; ENV.APP.rootElement = '#ember-testing'; } if (environment === 'production') { } return ENV;};
(1)environment
環境,有三個值:production development test,
(2)rootURL
根路徑,預設為’/’,
(3)locationType
用來表示url的規則,有4中規則hash history auto none。
既然說到了這裡,可以順帶說一下route.js。這個檔案,是用來做路由管理的,其中的有兩個變數localtion rootUrl,一般,我們都會在這裡,配置一下。如下:
import Ember from 'ember';import config from './config/environment';const Router = Ember.Router.extend({ location: config.locationType, rootURL: config.rootURL});Router.map(function() {});export default Router;
可以看到這裡的配置就是取自environment.js。
簡單說一下locationType的幾個值的意思。
以以下路由為例:
Router.map(function() { this.route('posts', function() { this.route('new'); });});
意思就是路徑post下有一個自路徑new
- hash,url為/#/post/new
- history,url為/posts/new
- none,這個情況比較特殊,是指url永遠都不會變,即時跳轉了,也就是說,ember不會儲存應用的路由狀態,這個一般情況下測試的時候會用
- auto,ember會選擇瀏覽器最支援的方式,一般為hash或者history,例如在ie9以下,會選擇hash。
(4)EmberENV
EmberENV下有一個重要的屬性FEATURES,這個主要用來控制新的特性,只有配置了才能使用,關於這裡的配置,老夫也不是很瞭解。根據官方文檔上的解釋,個人是這麼理解的:
在features.json裡有所有新的feature的狀態,但是他們不都是可以直接用的,他們的狀態分為一下幾種: false,即不存在也不能用,不管怎麼樣,都不會再正式構建中出現 true,存在且能直接用,可以直接在正式構建中出現 null,存在但是不能直接用,需要收到開啟,僅限於金絲雀版本以及beta版本
對於那種存在但是不能直接用null的特性,我們就需要手動去使用他,就是在屬性FEATURES裡面。
舉例:
var ENV = { EmberENV: { FEATURES: { 'link-to': true } }};
有一個方式,可以直接開啟所有就是把ENV.EmberENV.ENABLE_ALL_FEATURES設定為true。
這一部分,老夫也不能完全理解,大家可以看原文檔:ember feature
(5)APP
在這裡傳一些配置項,舉例而言,如果非同步請求的網域名稱不一致,那麼可以在這裡配置:
APP:{ serverDomain:'http://you.domain'}if (environment === 'development') { ENV.APP.serverDomain='http://you.domain:8080';}if (environment === 'test') { ENV.APP.serverDomain='http://you.domain:8080';}if (environment === 'production') { ENV.APP.serverDomain='http://you.domain:8080';}
用的時候只要引入一下就好了:
import ENV from 'your-application-name/config/environment'let result = Ember.$.getJson(ENV.APP.serverDomain).then((result) => {return result});
ember-cli-build.js
這個檔案,主要用來管理三方資源的。
先來看一下基礎的配置,構建時的配置項:
預設為:
var EmberApp = require('ember-cli/lib/broccoli/ember-app');module.exports = function(defaults){ var app = new EmberApp(defaults,{ });}
這裡需要注意,如果你在打包後,需要上傳到cdn的話,那麼就要加一些配置:
var EmberApp = require('ember-cli/lib/broccoli/ember-app');module.exports = function(defaults){ var app = new EmberApp(defaults,{ //你的cdn地址,注意,這個,只有在生產環境才會生效,也就是在構建的時候使用ember build --production prepend: 'http://path', //是否用md5,如果為null就是不用,那麼生產的檔案就是your-application-name.js,vendor.js以及your-application-name.css,vendor.css,如果為一個字串,那麼就是那個名字,否則,md5,產生的檔案類似於: your-application-name-dc477601773d4043b0c461b2a0ae8aef.js,不一一列舉。 customHash: null });}
在ember中,推薦的包管理工具為bower,例如,如果我們引入一個三方包,以最常用的bootstrap為例,
bower install bootstrap
除了這種方式,還可以直接把檔案放到vendor目錄下。
在把包下載或者是拷貝過來後,還沒有完事,必須要在ember-cli-build.js中進行配置:
app.import('vendor/package/package/a.css'); app.import('bower_component/bootstrap/dist/css/bootstrap.min.css');
以上就可以在構建的時候,自動構建到build/asserts目錄下。 下面主要說一下目錄的結構 app
這個檔案夾,使我們最重要的檔案夾,其中我們的代碼都會放在它下面,他的目錄結構如下所示:
如上文所說,ember是基於broccoli.js做目錄結構的管理的,所以說,結構也很清晰。 各種檔案夾
components controllers helpers models routes 分別對應於ember中的對應的概念,也就是component controller helper model route 。其中,template中放的是模板檔案,結構和上述類似,當使用ember-cli 命令列工具建立components 以及 routes的時候,會在對應的目錄下,建立模板檔案,其他的則沒有。
例如,當使用
ember g component a/b,那麼會建立components/a/b.js template/components/a/b.hbs。其他的同理。 app.js&resolver.js
這兩個檔案一般不需要變更
resolver.js 主要就是引用了ember-resolver的Resolver,就是用ES6重寫了一下resolver。
app.js主要用來構建的,能夠自動引入構建後的檔案。
這兩者我都不是十分瞭解,有大神能夠解釋一下也是極好的。 index.html
這個檔案,就是就是最外層的父模板,也就是根dom,這個模板中有幾個部分需要注意一下。
第一點為:其中有幾個引入的檔案,分別為vendor.css、 <project-name>.css、vendor.js、<project-name>.js,這個幾個檔案也就是編譯後產生的檔案。其中{{rootUrl}}也就是environment·js中的那個變數,預設為/ 不需要變動。如果是上傳到cdn的話,在ember-cli-build.js 中配置後,在生產環境會進行替換。
第二點為:{{content-for}}。這裡有一個helper {{content-for}},{{content-for}}為一個供外掛程式使用的鉤子,使得外掛程式可以向其中插入元素。在ember-cli的文檔中是這麼寫的:
The app/index.html file lays the foundation for your application. This is where the basic DOM structure is laid out, the title attribute is set, and stylesheet/javascript includes are done. In addition to this, app/index.html includes multiple hooks - {{content-for ‘head’}} and {{content-for ‘body’}} - that can be used by addons to inject content into your application’s head or body. These hooks need to be left in place for your application to function properly however, they can be safely ignored unless you are directly working with a particular addon.
以{{content-for 'head'}}而言,ember-cli就會在其中加入<meta name="appname/config/environment">這個head,如果你刪除了這個helper,那麼會報錯。
同理,{{content-for 'body'}}這個,會將app\templates\application.hbs插入進去。也就是body,使我們主要關注的內容。 app\templates\application.hbs
關於這個檔案,有必要多說兩句。如上所述,這個檔案其實就是body,我們所有的模板都渲染在這裡,要實現這樣的動態渲染,我們還需要安裝一個外掛程式liquid-fire liquid-fire.
首先是安裝:npm install --save-dev liquid-fire
安裝完成後,新增檔案app/transitions.js。這個檔案,定義了渲染規則。同時,也新增了一些helper,為liquid-if liquid-with liquid-outlet link-to。因為正常的helper沒有渲染這個概念。
舉例,我們可以這麼寫我們的application.hbs
{{liquid-outlet class="body-class"}}//or {{liquid-box class="body-class"}}
那麼,我們以後每一個產生的route,就都會渲染在這裡。
app/transitions.js?定義了如何渲染,比如說一下的內容:
export default function(){ this.transition( this.fromRoute('route.route1'), this.toRoute('route.route2'), this.use('toRight'), this.reverse('toLeft'), );}
當從路由route1 變化到 route2時,會有一個從左至右的動畫,反之,子路由route2 變化到 route1時,會有一個從右至左的動畫。這個如果不寫的話,那麼就是直接替換。當然還有一些進階的規則,自己可以看文檔。 其他內容
例如想要修改連接埠(預設為8000),那麼只需要修改.ember-cli檔案,如下:
{"port":8080}
取消原型鏈整合,ember中的Array string 都是整合了原有的原型鏈,會有一些額外的方法以及屬性,預設是繼承的,也就是說,你採用以下方法建立的都是一樣的東西
let a = [1,2,3];let b = Ember.A([1,2,3]);a.includes(1);//trueb.includes(1);//true
禁用方式如下,修改config/environment.js
ENV = { EmberENV: { EXTEND_PROTOTYPES: false//全部禁用 /** * 部分禁用 EXTEND_PROTOTYPES: { String: false, Array: true }*/ }}
注意,如果禁用了的話,那麼就不會享受到一些雙向繫結的好處了,比如使用{{#each}}來遍曆Array的話,如果變化了就沒法感知了。在此建議,全部使用Ember.A來初始化資料,同時不要禁用繼承。
https://guides.emberjs.com/v2.11.0/configuring-ember/configuring-your-app/
https://guides.emberjs.com/v2.11.0/configuring-ember/configuring-ember-cli/
https://guides.emberjs.com/v2.11.0/configuring-ember/disabling-prototype-extensions/
https://guides.emberjs.com/v2.11.0/configuring-ember/specifying-url-type/
https://www.airpair.com/ember.js/posts/animations-in-emberjs-with-liquidfire
https://ember-cli.com/user-guide/