Ember学习(2):Ember的命名约定

英文原址:http://emberjs.com/guides/concepts/naming-conventions/

Ember.js使用命名约定来连接你的各种对象,从而避免使用过多的引用。你需要对你的route,controller和template使用这些约定。通常你可以推测哪些名字,但是这个指导集中地给出了一个大纲,包含了所有的命名约定。在下面的列子中,“App”是我们选定的命名空间,或者说它代表了你创建的Ember应用,但是你也可以为你的应用选择任何其他的名字。我们后面将会向你展示如何创建一个Ember应用,现在让我们先专心学习这些命名约定。


The Application(应用)

当你的应用启动时,Ember会寻找下面这些对象:
  • App.ApplicationRoute
  • App.ApplicationController
  • "application" template
Ember.js会将“application” template当做主模板来显示。如果定义了App.ApplicationController,Ember会创建一个App.ApplicationController的实例,并将设定为application template的controller。这意味着,application模板可以从这个controller中获取数据。

如果你的应用定义了App.ApplicationRoute,Ember在显示application template之前会先调用router的钩子函数。Hooks(钩子函数)被实现成方法,给你提供了一个Ember对象生命周期的扩展接口,来插入你自己的代码以改变Ember默认的行为以满足你的需要。Ember提供许多的Hook来支持你各种不同的目的(比如model和setupcontroller hook)。在下面的例子中,App.ApplicationRoute,它是一个Ember.Route对象,实现了setupController钩子函数。

下面是一个简单的例子关于如何使用route,controller和template:
App.ApplicationRoute = Ember.Route.extend({
  setupController: function(controller) {
    // `controller` is the instance of ApplicationController
    controller.set('title', "Hello world!");
  }
});

App.ApplicationController = Ember.Controller.extend({
  appName: 'My First Example'
});


{{appName}}

{{title}}

在Ember应用中,你必须总是将你的controller指定成类,框架负责初始化它们,并且提供给你的模板。这使得测试你的controll变得非常简单,并且保证你的整个应用对于每种controller只共享一个对应controller的实例。

Simple Route(简单路由)

你的每个route都会有一个controller,还会有一个和route同名的template。让我们从一个简单的route开始:
App.Router.map(function() {
  this.route('favorites');
});
如果你的用户导航到“/favorites”,Ember会查找下面的对象:
  • App.FavoritesRoute
  • App.FavoritesController
  • the favorites template
Ember会将favorites模板显示在application模板的{{outlet}}中,还会为这个模板设置一个App.FavoritesController的实例。如果你的应用定义了App.FavoritesRoute,框架会在显示模板前调用它。你猜对了,这个过程会重复的递归下去。对于一个像App.FavoritesRoute这样的route,你可能会实现一个model钩子函数,来指定你的controller使用什么model供你的模板显示。下面是一个例子:
App.FavoritesRoute = Ember.Route.extend({
  model: function() {
    // the model is an Array of all of the posts
    return this.store.find('post');
  }
});
在这个例子里,我们没有提供FavoritesController,因为这个model是一个数组,Ember会自动的生成一个Ember.ArrayController的实例,这个实例会将数组数据呈现为model。你可以将ArrayController看成是model本身,这有两点好处:
你可以在任何时刻替换controller的model,而不需要通知模板有关的改变
controller本身可以提供额外的计算型属性(computed properties),或者模板特定的状态,这些都不属于model这个层次。这使得view,controller和model之间的关系可以干净的分离。

模板可以迭代访问controller的元素:
    {{#each controller}}
  • {{title}}
  • {{/each}}

Dynamic Segments(动态字段)

如果route使用了dynamic segment,这个route的model就会基于用户提供的dynamic segment的值来生成。考虑下面的router定义:
App.Router.map(function() {
  this.resource('post', { path: '/posts/:post_id' });
});
在这个例子中route的名字是post,因此Ember会查找下面的对象:
  • App.PostRoute
  • App.PostController
  • the post template

你的route的model钩子函数会将:post_id参数转换成一个model,route的serialize钩子函数会将一个model数据转换回一个URL中的参数(比方说,当生成一个指向model对象的链接)。

App.PostRoute = Ember.Route.extend({
  model: function(params) {
    return this.store.find('post', params.post_id);
  },

  serialize: function(post) {
    return { post_id: post.get('id') };
  }
});

因为这个用法是如此的通用,它被设计成了route的默认行为。

如果你的dynamic segment以_id结尾,那默认的model钩子函数会将名字的前面部分解释为定义在Application命名空间下的model的类名(post变成App.Post),然后Ember会在这个类上调用find方法,将_id部分对应的实际值作为参数传入以查找含有该id的对应实例。而默认的serialize钩子函数会将model对象的id属性返回回来以插入URL。


Route, Controller and Template defaults(路由,控制器和模板的默认行为)

如果你没有定义post route定义一个路由处理类(App.PostRoute),Ember仍然会创建一个App.PostController的实例,然后用它来显示post模板。

如果你没有定义一个对应的controller(App.PostController),Ember仍然会基于route的model钩子函数的返回值,给你自动创建一个。如果model钩子函数的返回值是Array,你会得到一个ArrayController,否则你会得到一个ObjectController。

如果你没有定义一个对应的模板(post template),Ember不会显示任何东西


Nesting(嵌套)

你可以在resource下嵌套route:
App.Router.map(function() {
  this.resource('posts', function() { // the `posts` route
    this.route('favorites');          // the `posts.favorites` route
    this.resource('post');            // the `post` route
  });
});

resource是一个route,controller以及template名字的开始,即使post resource是嵌套的,它的route名字仍然是App.PostRoute,它的controller名字是App.PostController,而它的模板名字是post。当你将一个route嵌套进resource里,route的名字会被添加在resource名字的后面,以一个“.”来连接。
下面是上面定义的router根据命名约定生成的route名称:
Route Name Controller Route Template
posts PostsController PostsRoute posts
posts.favorites PostsFavoritesController PostsFavoritesRoute posts/favorites
post PostController PostRoute post
大拇指规则:将resource用于名词对应的概念,而将route用于形容词或者动词对应的概念。这能保证嵌套不会产生不可理喻的长名字,而同时可以避免一个常用的形容词和动词型的概念的名称冲突。

The Index Route (Index路由)

在每一个嵌套的层次(包括最顶层),Ember自动为“/"路径提供了一个默认的名字叫index的route。举个例子,如果你像下面这样定义:
App.Router.map(function() {
  this.route('favorites');
});
它等同于:
App.Router.map(function() {
  this.route('index', { path: '/' });
  this.route('favorites');
});
如果用户访问"/", Ember会查找如下对象:
  • App.IndexRoute
  • App.IndexController
  • the index template
这个index模板会被显示在application模板的{{outlet}}中。如果用户访问到”/favorites“,Ember就会用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",当前的route会是posts.index,Ember会找如下的对象:
  • App.PostsIndexRoute
  • App.PostsIndexController
  • The posts/index template
首先,posts模板会被显示在application模板的{{outlet}}中。然后,posts/index模板会被显示在posts模板中的{{outlet}}处。如果用户接着导航到/posts/favorites,Ember会用posts/favorites模板替换{{outlet}}中之前的内容。

你可能感兴趣的:(Ember)