Model
在默认情况下,model钩子返回的值,会设置为关联的控制器的model属性。例如,如果App.PostsRoute通过model钩子返回了一个对象,这个对象会设置为App.PostsController的model属性。
(模板是如何知道该使用哪个模型进行渲染的呢?模板通过查找其关联的控制器的model属性来进行渲染。例如,photos模板将会使用App.PhotosController的model属性来进行渲染。)
Ember Data
在Ember中,每个路由都有与之相关联的一个模型。这个模型可以通过路由的model钩子进行设置,可以通过给{{link-to}}传入一个参数,也可以通过调用路由的transitionTo()方法。
对于简单的应用来说,可以通过jQuery来从服务器加载JSON数据,并将这些JSON数据对象作为模型。
但是,使用一个模型库来管理查询、更改和将更改保存回服务器,将会大大的简化代码,同时也能提升应用的健壮性和性能。
许多Ember应用使用Ember Data来处理模型。Ember Data是一个与Ember.js紧密结合在一起的代码库,简化了客户端从服务器获取记录,在本地进行缓存以提高性能,保存修改到服务器,创建新的记录等一系列的操作。
Ember Data不需要进行任何配置,就可以实现通过服务端提供的RESTful JSON API加载和保存记录以及它们的管理关系,这些操作都遵从于特定的惯例。
目前,Ember Data还是一个独立于Ember.js的库。在Ember Data被作为标准发行版的一部分之前,你可以在builds.emberjs.com下载最新的版本。
仓库Store
仓库是应用存放记录的中心仓库。你可以认为仓库是应用的所有数据的缓存。应用的控制器和路由都可以访问这个共享的仓库;当它们需要显示或者修改一个记录时,首先就需要访问仓库。
DS.Store的实例会被自动创建,并且该实例被应用中所有的对象所共享。
模型
模型是一个类,它定义了需要呈现给用户的数据的属性和行为。任何用户期望在其离开应用然后再回到应用时能够看见的数据,都应该通过模型来表示。
例如,如果正在编写一个可以给饭店下单的Web应用,那么这个应用中应该包含Order、LineItem和MenuItem这样的模型。
模型定义了服务器提供的数据的类型。
模型也声明了它与其他对象的关系。
模型本身没有任何数据;模型只定义了其实例所具有的属性和行为,而这些实例被称为记录。
记录
记录是模型的实例,包含了从服务器端加载而来的数据。应用本身也可以创建新的记录,以及将新记录保存到服务器端。
记录由以下两个属性来唯一标识:
- 模型类型
- 一个全局唯一的ID
ID通常是在服务器端第一次创建记录的时候设定的,当然也可以在客户端生成ID。
适配器
适配器是一个了解特定的服务器后端的对象,主要负责将对记录的请求和变更转换为正确的向服务器端的请求调用。
例如,如果应用需要一个ID为1的person记录,那么Ember Data是如何加载这个对象的呢?是通过HTTP,还是Websocket?如果是通过HTTP,那么URL会是/person/1,还是/resources/people/1呢?
适配器负责处理所有类似的问题。无论何时,当应用需要从仓库中获取一个没有被缓存的记录时,应用就会访问适配器来获取这个记录。如果改变了一个记录并准备保存改变时,仓库会将记录传递给适配器,然后由适配器负责将数据发送给服务器端,并确认保存是否成功。
架构简介
应用第一次从仓库获取一个记录时,仓库会发现本地缓存并不存在一份被请求的记录的副本,这时会向适配器发请求。适配器将从持久层去获取记录;通常情况下,持久层都是一个HTTP服务,通过该服务可以获取到记录的一个JSON表示。
参考文献
- http://emberjs-cn.github.io/guides/models/
杂项
Route
: A route is an object that tells the template which model it should display.
流程
- No matter how the URL gets set, the first thing that happens is that the Ember
router
maps the URL to aroute handler
. - The
route handler
then typically does two things:- It renders a template.
- It loads a model that is then available to the template.
Components
consist of two parts: a template written in Handlebars, and a source file written in JavaScript that defines the component's behavior.
When we call this.store.findAll('rental')
, Ember Data will make a GET request to /rentals
.
In certain cases, you will want to pass arguments to _super() before or after overriding.
One common example is when overriding the normalizeResponse() hook in one of Ember-Data's serializers.
A handy shortcut for this is to use a "spread operator", like ...arguments:
代码语言:javascript复制normalizeResponse(store, primaryModelClass, payload, id, requestType) {
// Customize my JSON payload for Ember-Data
return this._super(...arguments);
}
The above example returns the original arguments (after your customizations) back to the parent class, so it can continue with its normal operations.
If you are subclassing a framework class, like Ember.Component
, and you override the init()
method, make sure you call this._super(...arguments)
! If you don't, a parent class may not have an opportunity to do important setup work, and you'll see strange behavior in your application.
Observers :
- Observers are especially useful when you need to perform some behavior after a binding has finished synchronizing.
- If you never get() a computed property, its observers will not fire even if its dependent keys change. You can think of the value changing from one unknown value to another.
It's important that we include some information in the URL about not only which template to display, but also which model. In Ember, this is accomplished by defining routes with dynamic segments
. 详情见:https://guides.emberjs.com/v2.5.0/routing/specifying-a-routes-model/#toc_dynamic-models
Objects in Ember
- JavaScript objects don't support the observation of property value changes. Consequently, if an object is going to participate in Ember's binding system you may see an Ember.Object instead of a plain object.Ember.Object also provides a class system, supporting features like mixins and constructor methods.
- Ember also extends the JavaScript Array prototype with its Ember.Enumerable interface to provide change observation for arrays.
- Finally, Ember extends the String prototype with a few formatting and localization methods.
Classes and Instances
通过一段代码来理解:
代码语言:javascript复制Person = Ember.Object.extend({
say(thing) {
var name = this.get('name');
alert(`${name} says: ${thing}`);
}
});
Soldier = Person.extend({
say(thing) {
// this will call the method in the parent class (Person#say), appending
// the string ', sir!' to the variable `thing` passed in
this._super(`${thing}, sir!`);
}
});
var yehuda = Soldier.create({
name: 'Yehuda Katz'
});
yehuda.say('Yes'); // alerts "Yehuda Katz says: Yes, sir!"
Accessing Object Properties
When accessing the properties of an object, use the get()
and set()
accessor methods:
var person = Person.create();
var name = person.get('name');
person.set('name', 'Tobias Funke');
Make sure to use these accessor methods; otherwise, computed properties won't recalculate, observers won't fire, and templates won't update.