目录 [−]
- 使用Ember.Object的extend定义新类
- 计算属性Computed Properties
- @each计算
- observers 是同步的
- Ember.computed('aaa', function(){}), Ember.observer('aaa', function () {})
- reopen覆盖
- 架构
- Store
- model 和 record
- adapter
- Serializer
- 属性定义时,attr()类型可以不设置
- One-to-One, One-to-Many和Many-to-Many. hasMany
- 增删改查
- model的一些方法
- Adapter的 URL Conventions
- namespace
- normalizeHash
- Adapter的其它属性
- 定制Transformations
Ember.js是一款用来创建炫酷的Web应用程序的JavaScript MV* 框架。 正像AngularJS,Backbone.js一样正在广泛的应用于现代的Web开发中, 知名用户包括 Yahoo!, Groupon, 和 ZenDesk.
总的来说, Ember.js还在推广之中, 国内使用它做开发的还比较少, 官方的文档也不是很完备。 所以这篇文章记录了我使用Ember中收集的一些技巧,诀窍和最佳实践, 并且会不断的更新。
想了解Ember.js和其它JavaScript框架的区别, 可以看这篇文章: AngularJS vs. Backbone.js vs. Ember.js。
通用
核心概念
Template: describes the user interface of your application by Handlebars。
Router: The router translates a URL into a series of nested templates, each backed by a model.
Route: A route is an object that tells the template which model it should display.
Model: A model is an object that stores persistent state.
Controller: A controller is an object that stores application state. A template can optionally have a controller in addition to a model, and can retrieve properties from both.
Component: A component is a custom HTML tag whose behavior you implement using JavaScript and whose appearance you describe using Handlebars templates.
命名约定
Ember.js 由Yehuda Katz创建, 他还是jQuery, Ruby on Rails 和 SproutCore核心开发组的成员。 就像Katz其它项目一样, 命名约定(convention over configuration)被广泛使用。
你可以查看这篇文章了解Ember.js的命名: Ember命名规则
带Binding
后缀的属性自动转为Ember.Binding
对象
valueBinding: "MyApp.someController.title"
will create a binding from MyApp.someController.title to the value property of your object instance automatically. Now the two values will be kept in sync.
单向绑定: bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles")
View vs. Component
一句话, 尽量使用Component而不是View
Contrarily to Ember views, an Ember component is not connected to a related Ember Controller, since it is self contained, in which regards both the data and events that it handles. In this sense, components are easier to reuse in different places of the application, as well as in different applications.
http://raulbrito.github.io/articles/thoughts-on-ember-views-vs-components/
Controller
转到其它页面
|
|
转到指定的url在测试和调试的时候也可以使用,正式产品中还少用到。
|
|
访问其它Controller. needs
属性
|
|
needs
定义为此controller要访问的其它controllers的数组。
嵌套的controller也可以访问:
|
|
使用send
调用定义的action
|
|
主动触发property变动事件
propertyDidChange
, propertyWillChange
即使你没有调用get
或set
也能触发事件。
Route
一些钩子hook
- activate Router进入此route时
- beforeModel 在model之前调用
- model 获取model数据
- afterModel 当model获取到。 主要获取model时使用的是async/promise语法。
- renderTemplate 渲染模版的钩子
- setupController 为当前route设置钩子
controllerFor
在route中得到其它的controller对象。参数为the name of the route or controller。
modelFor
得到父Route的model
|
|
transitionTo
, intermediateTransitionTo
跳转到另外的route. The route may be either a single route or route path:
|
|
refresh
刷新本route及子route的model
渲染非默认的模版
|
|
Model
使用Ember.Object
的extend
定义新类
|
|
_super()
父类的方法。
创建实例: var person = App.Person.create();
计算属性Computed Properties
computed properties let you declare functions as properties.
|
|
设置计算属性:
|
|
@each
计算
|
|
数组元素的每一个更新 (CUD或者数组重新被赋值)都会触发重新计算。
observers
是同步的
运行一次Ember.run.once
Observers 在对象初始化之前不会被触发。如果想init时被触发,加上.on(\'init\')
|
|
增加observer:
|
|
Ember.computed('aaa', function(){})
, Ember.observer('aaa', function () {})
可以写为 function(){}.property('aaaa')
, function(){}.observers('aaa')
reopen
覆盖
|
|
Person.create().get('isPerson') // true
架构
Store
|
|
model 和 record
record是model的一个实例
adapter
负责将record和数据持久化后台结合起来。DS.RESTAdapter
, FixtureAdapter
Serializer
A serializer is responsible for turning a raw JSON payload returned from your server into a record object.
负责将一个纯的JSON转换成record对象。
属性定义时,attr()
类型可以不设置
后台服务器返回啥就是啥。也可以指定类型。类型只能是string
,number
,boolean
和date
。
Date遵循 ISO 8601. 例如: 2014-05-27T12:54:01。
|
|
One-to-One, One-to-Many和Many-to-Many. hasMany
|
|
增删改查
- createRecord
|
|
- deleteRecord/save 或者 destroyRecord
store.find('post', 1).then(function (post) {
post.deleteRecord();
post.get('isDeleted'); // => true
post.save(); // => DELETE to /posts/1
});
// OR
store.find('post', 2).then(function (post) {
post.destroyRecord(); // => DELETE to /posts/2
});
- push到store的缓存
|
|
- save
|
|
- find
根据参数内部用find
,findAll
和findQuery
实现。
|
|
model的一些方法
incrementProperty
changedAttributes
Adapter的 URL Conventions
Action | HTTP Verb | URL |
---|---|---|
Find | GET | /people/123 |
Find All | GET | /people |
Update | PUT | /people/123 |
Create | POST | /people |
Delete | DELETE | /people/123 |
namespace
|
|
Requests for App.Person
would now target /api/1/people/1
.
normalizeHash
如果想将JSON中的lastNameOfPerson
关联model的lastName
|
|
Adapter的其它属性
|
|
定制Transformations
除了内建类型string
, number
, boolean
, and date
,你可以定义新类型。
|
|
数组类型
|
|
View
定义view
|
|
定制view元素
|
|
|
|
内建的view
- Ember.Checkbox
- Ember.TextField
- Ember.TextArea
- Ember.Select
Template
数据枚举 Ember.Enumerable
forEach
|
|
可枚举的类型
- Array: 实现纯javascript Array并且实现 Enumerable interface
- Ember.ArrayController
- Ember.Set
toArray()
得到纯javascript数组
firstObject
, lastObject
MAP
|
|
|
|
filter
|
|
|
|
Aggregate
every
和some
判断集合所有元素或者部分元素是否满足条件。
也可以
|
|
Helper
bind class
class可以是
- a string return value of an object's property.
<img \{\{bind-attr \class="view.someProperty}}>
- a boolean return value of an object's property. true插入类名, false移除类名或替换类名
<img \{\{bind-attr \class="view.someBool:class-name-if-true"}}>
<img \{\{bind-attr \class="view.someBool:class-name-if-true:class-name-if-false"}}>
- a hard-coded value
<img \{\{bind-attr \class=":class-name-to-always-apply"}}>
复合型: <img \{\{bind-attr \class=":class-name-to-always-apply view.someBool:class-name-if-true view.someProperty"}}>
each
helper
|
|
集合为空时使用\{\{#each}}
|
|
指定渲染用的view
|
|
默认遍历controller的属性,可以指定itemController
:
|
|
if-else
|
|
另外还提供了unless
|
|
outlet
一个模版占位符。
或
|
|
|
|
partial
渲染另外一个页面而不改变上下文
|
|
render
使用包含的上下文
{{render "navigation"}}
Calling {{render}} from within a template will insert another template that matches the provided name. The inserted template will access its properties on its own controller (rather than the controller of the parent template).
view
{{view}} inserts a new instance of an Ember.View into a template passing its options to the Ember.View's create method and using the supplied block as the view's own template.
view
, partial
和render
的区别
General
Helper | Template | Model | View | Controller |
---|---|---|---|---|
{{partial}} | Specified Template | Current Model | Current View | Current Controller |
{{view}} | View's Template | Current Model | Specified View | Current Controller |
{{render}} | View's Template | Specified Model | Specified View | Specified Controller |
Specific
Helper | Template | Model | View | Controller |
---|---|---|---|---|
{{partial "author"}} | author.hbs | Post | App.PostView | App.PostController |
{{view "author"}} | author.hbs | Post | App.AuthorView | App.PostController |
{{render "author" author}} | author.hbs | Author | App.AuthorView App.AuthorController |
with
changes scope, as
|
|
link-to
link-to (routeName, context, options) String
提供tagName: \{\{#link-to 'photoGallery' tagName="li"}} Great Hamster Photos\{\{/link-to}}
自动添加\class="active"
指定model: \{\{#link-to 'photoGallery' aPhoto}} \{\{aPhoto.title}}\{\{/link-to}}
, for dynamic segments或者多个model或者model id: \{\{#link-to 'photoGallery' aPhotoId}} \{\{aPhoto.title}}\{\{/link-to}}
input
\{\{input type="text" value=firstName disabled=entryNotAllowed size="50"}}
支持action: \{\{input action="submit"}}
支持的actions: enter
insert-newline
escape-press
focus-\in
focus-out
key-press
如\{\{input focus-\in="alertMessage"}}
checkbox: \{\{input type="checkbox" name="isAdmin"}}
自定义helper
简单语法
|
|
使用\{\{highlight name}}
依赖参数
|
|
使用{{fullName person}}
定制view helper
|
|
使用\{\{calendar}}
或者\{\{view "calendar"}}
Component
HTML代码代替hbs模版
在Component和View的实现时,可以直接使用Ember.Handlebars.compile
直接写HTML代码,不用定义一个hbs模版文件。
|
|
定义组件
- template必须以
components/
开头。比如组件0
的模版为components/blog-post
- 组件名必须包含破折号dash 。
blog-post
合法但是post
不合法。 - 继承
Ember.Component
或子类。blog-post
的类为App.BlogPostComponent
组件的钩子(Hook)函数
传给组件参数
\{\{blog-post title=name}}
, name是外部对象的属性
一句话componentProperty=outerProperty
定制组件的属性
类似view。
从组件发送action给其它应用
When a component is used inside a template, it has the ability to send actions to that template's controller and routes. These allow the component to inform the application when important events, such as the user clicking a particular element in a component, occur.
组件\{\{my-button action="showUser"}}
|
|
`this.sendAction('action', param1, param2);
|
|
|
|
|
|
多action: \{\{user-form submit="createUser" cancel="cancelUserCreation"}}