2013年5月16日星期四

【Ember.js指南 序二】命名慣例

為了統一整個應用程式,Ember.js規定了各元素的命名慣例。

應用程式

假設你把網站命名為 App ,當Ember.js初始化時,將首先尋找以下的物件(Object):
  • App.ApplicationRoute
  • App.ApplicationController
  • application/未有命名的 模板 (模板將於第三部分介紹)
Ember.js首先會渲染application作為主模板,並將其連結至App.ApplicationController(如有設置),這樣模板就可以使用ApplicationController的屬性。



如果設置了App.ApplicationRoute,Ember.js將先調用路由器(Router)的hooks,然後才會渲染application模板。
Hooking: Code handles intercepted function calls, events or messages is called a "hook".

處理截獲的函數調用,事件或訊息的代碼被稱為「掛鉤」。
簡單來說,就是不同狀態的函數

以下是一個使用了路由、控制器和模板的例子:
App.ApplicationRoute = Ember.Route.extend({
  setupController: function(controller) {
    // `controller` 指向 ApplicationController 的實體
    controller.set('title', "Hello world!");
  }
});

App.ApplicationController = Ember.Controller.extend({
  appName: 'My First Example'
});
在Ember.js應用中,你須將控制器指定為類別(Class),例如 Ember.Controller,程式框框架負責建立實體,並提供給模板。

這簡化了測試控制器的工作,並確保應用只共享一個控制器的實體。

簡單的路由 (Route)

對於每一個路由,都有與其同名的控制器和模板。

以這個路由為例:
App.Router.map(function() {
  this.route('favorites');
});
如果訪問/favourites,Ember.js會尋找:
  • App.FavoritesRoute
  • App.FavoritesController
  • favorites 模板
然後將 favorites模板 渲染到 application模板 的 {{outlet}} 裏,並為App.FavoritesController建立實體,作為模板的控制器。

如提供了App.FavoritesRoute,它在渲染模板前會先被調用。

對於App.FavoritesRoute,你可能會在model掛鉤指定模型給控制器,並呈現在模板。下面是一個例子:
App.FavoritesRoute = Ember.Route.extend({
  model: function() {
    // model 是一個放了所有posts的陣列(Array)
    return App.Post.find();
  }
});
即使沒有提供/FavoritesController,但model返回的是陣列,所以Ember.js會自動提供Ember.ArrayController,將返回的陣列設為controller的model。

你可以將ArrayController視作模型,這樣有以下的優點:
  • 任意替換模型,無須考慮視圖的變化
  • 控制器可以提供額外不屬於模型層的:可計算屬性(Computed Properties) 或 特定的視圖狀態(view-specific state)。這清晰地分隔了視圖,控制器和模型。
設置model後,可使用模板迭代控制器中的元素:
<ul>
  {{#each controller}}
    <li>{{title}}</li>
  {{/each}}
</ul>

動態(網址)段 (Dynamic Segments)

如果路由使用了動態段,模型將基於用戶提供給段的值。考慮以下路由的定義:
App.Router.map(function() {
  this.resource('post', { path: '/posts/:post_id' });
});
在此,路由的名稱為post,所以Ember.js會尋找:
  • App.PostRoute
  • App.PostController
  • post 模板
路由的model掛鉤將動態參數:post_id轉換到模型。而serialize掛鉤會為路由把模型轉為URL參數 (例如,在為模型產生鍵結時)
App.PostRoute = Ember.Route.extend({
  model: function(params) {
    return App.Post.find(params.post_id);
  },

  serialize: function(post) {
    return { post_id: post.get('id') };
  }
});
由於這個模式太常見,所以它是預設的處理程序。
  • 如果動態段以_id作結,預設的model掛鉤會將字首post轉為應用中的App.Post模型類,然後把段的值傳到類的find函數
  • 預設的serialize掛鉤會從模型的id獲取路由的動態段

路由,控制器和預設模板

如果沒有為post路由指定處理程序(App.PostRoute),Ember.js仍然會使用App.PostController的實體來渲染post模板。

如果沒有指定控制器(App.PostController),Ember會根據路由model掛鉤的返回值自動創建。模型是陣列會創建ArrayController,否則為ObjectController

如果沒有指定post模板,Ember.js什麼也不會渲染。

巢狀路由

你可以在一個resource內嵌套路由。
App.Router.map(function() {
  this.resource('posts', function() { // `posts` 路由
    this.route('favorites');          // `posts.favorites` 路由
    this.resource('post');            // `post` 路由
  });
});
資源為路由,控制器或模板的起始名稱。即使post資源被嵌套了,它的路由的名稱仍是App.PostRoute,控制器名稱是App.PostController,範本名稱是post

如果在資源內嵌套了路由,該路由的名稱將變為資源名稱.路由名稱

以下為此路由器中,各個路由的命名慣例:

路由名稱 控制器 路由 模板
posts PostsController PostsRoute posts
posts.favorites PostsFavoritesController PostsFavoritesRoute posts/favorites
post PostController PostRoute post

命名的原則就是:資源名稱為名詞,路由名稱應為形容詞(favorites)或動詞(edit)。這確保嵌套時不會產生冗長的名稱,而且避免常見形容詞和動詞的衝突。

路由的首頁

巢狀路由的每層(包括最上層),Ember.js自動為/路徑提供了一個名稱為index的路由。

例如,假如你寫了如下這樣一個簡單的路由:
App.Router.map(function() {
  this.route('favorites');
});
這相當於:
App.Router.map(function() {
  this.route('index', { path: '/' });
  this.route('favorites');
});
如果用戶訪問/路徑,Ember.js會尋找:
  • App.IndexRoute
  • App.IndexController
  • index模板
index模板將渲染到application模板中的{{outlet}}。如果用戶訪問/favorites, Ember.js將用favorites模板取代index模板。

例如這個路由器:
App.Router.map(function() {
  this.resource('posts', function() {
    this.route('favorites');
  });
});
相當於:
App.Router.map(function() {
  this.route('index', { path: '/' });
  this.resource('posts', function() {
    this.route('index', { path: '/' });
    this.route('favorites');
  });
});
如果用戶訪問/posts,當前路由就是posts.index。Ember.js將尋找:
  • App.PostsIndexRoute
  • App.PostsIndexController
  • posts/index模板
首先,posts模板將渲染到application模板中的{{outlet}}。然後,posts/index模板將渲染到posts模板的{{outlet}}

如果用戶訪問/posts/favorites,Ember.js會使用posts/favorites模板替換posts模板中的{{outlet}}

翻譯自:http://emberjs.com/guides/concepts/naming-conventions/
參考:http://emberjs.cn/guides/concepts/naming-conventions/

7 則留言: