从本篇开始进入控制器,controller在Ember2.0开始越来越精简了,职责也更加单一——处理逻辑。
下面是准备工作。 重新创建一个Ember项目,仍旧使用的是Ember CLI命令创建。
ember new chapter5_controllerscd chapter5_controllersember server
在浏览器执行项目,看到如下信息说明项目搭建成功。 Welcome to Ember。
1,控制器简介
控制器与组件非常相似,由此,在未来的新版本中很有可能组件将会完全取代控制器,很可能随着Ember版本的更新控制器将退出Ember。目前的版本中组件还不能直接通过路由访问,需要通过模板调用才能使用组件,但是未来的版本会解决这个问题,到时候controller可能就真的从Ember退出了!
正因如此,模块化的Ember应用很少用到controller。即便是使用了controller也是为了处理下面的两件事情:
controller主要是为了维持当前路由状态。一般来说,model的属性会保存到服务器,但是controller的属性却不会保存到服务器。- 组件上的动作需要通过
controller层转到route层。
模板上下文的渲染是通过当前controller的路由处理的。Ember所追随的理念是“约定优于配置”,这也就意味着如果你只需要一个controller 你就创建一个,而不是一切为了“便于工作”。
下面的例子是演示路由显示blog post。假设模板blog-post用于展示模型blog-post的数据,并在这个模型包含如下属性(隐含属性id,因为在model中不需要手动指定id属性):
- title
- intro
- body
- author
model定义如下:
// app/models/blog-post.jsimport DS from 'ember-data';export default DS.Model.extend({title: DS.attr('string'), // 属性默认为string类型,可以不指定intro: DS.attr('string'),body: DS.attr('string'),author: DS.attr('string')});
在route层增加测试数据,直接返回一个model对象。
// app/routes/blog-post.jsimport Ember from 'ember';export default Ember.Route.extend({model: function() {var blogPost = this.store.createRecord('blog-post', {title: 'DEFINING A COMPONENT', // 属性默认为string类型,可以不指定intro: "Components must have at least one dash in their name. ",body: "Components must have at least one dash in their name. So blog-post is an acceptable name, and so is audio-player-controls, but post is not. This prevents clashes with current or future HTML element names, aligns Ember components with the W3C Custom Elements spec, and ensures Ember detects the components automatically.",author: 'ubuntuvim'});// 直接返回一个model,或者你可以返回promises,return blogPost;}});
显示信息的模板如下:
<!-- app/templates/blog-post.hbs --><h1>{{model.title}}</h1><h2>{{model.author}}</h2><div class="intro">{{model.intro}}</div><hr><div class="body">{{model.body}}</div>
如果你的代码没有编写错误那么也会得到如下结果:

Welcome to Ember是主模板的信息,你可以在application.hbs中删除,但是记得不要删除{{outlet}},否则什么信息也不显示。
这个例子中没有显示任何特定的属性或者指定的动作(action)。此时,控制器的model属性所扮演的角色仅仅是模型属性的pass-through(或代理)。
注意:控制器获取的model是从route得到的。
下面为这个例子增加一个功能:用户可以点击标题触发显示或者隐藏post的内容。通过一个属性isExpanded控制,下面分别修改模板和控制器的代码。
// app/controllers/blog-post.jsimport Ember from 'ember';export default Ember.Controller.extend({isExpanded: false, //默认不显示bodyactions: {toggleBody: function() {this.toggleProperty('isExpanded');}}});
在controller中增加一个属性isExpanded,如果你不在controller中定义这个属性也是可以的。对于这个controller代码的解释请看“{{action}} 助手”章节。
<!-- app/templates/blog-post.hbs --><h1>{{model.title}}</h1><h2>{{model.author}}</h2><div class="intro">{{model.intro}}</div><hr>{{#if isExpanded}}<button {{action 'toggleBody'}}>hide body</button><div class="body">{{model.body}}</div>{{else}}<button {{action 'toggleBody'}}>Show body</button>{{/if}}
在模板中使用if助手判断isExpanded的值,如果为true则显示body,否则不显示。
页面加载之后结果如下,首先是不显示body内容,点击按钮“Show body”则显示内容,并且按钮变为“hide body”。然后在点击这个按钮则不显示body内容。


到此controller的职责你应该大致了解了,其主要的作用是逻辑的判断、处理,比如这里例子中判断body内容的显示与否,其实你也可以把controller类中的处理代码放在route类中也可以实现这个效果,但是要作为model的属性返回(把isExpanded当做model的属性处理),请读者自己动手试试,但是把逻辑放到route又会使得route变得“不专一”了,route的主要职责是初始化数据的。我想这也是Ember还留着controller的原因之一吧!!
转载本站内容时,请务必注明来自W3xue,违者必究。


优化或报错有奖
皖公网安备34020702000426号