
记录检索
Ember Data 存储提供了一个接口,用于检索单一类型的记录。
检索单个记录
使用 store.findRecord() 是根据记录的类型和ID进行检索,通过返回一个 promise 处理满足检索条件的记录:
// GET /blog-posts/1
this.store
.findRecord("blog-post", 1) // => GET /blog-posts/1
.then(function (blogPost) {
// 解析数据
});
使用 store.peekRecord() 是根据记录的类型和ID进行,不会发出HTTP请求,只有当记录已经存在于 store 中时,才会被返回:
const blogPost = this.store.peekRecord("blog-post", 1); // => 没有HTTP请求复制代码
检索多个记录
使用 store.findAll() 检索指定类型的所有记录:
// GET /blog-posts
this.store
.findAll("blog-post") // => GET /blog-posts
.then(function (blogPosts) {
// 解析记录数据
});
使用store.peekall() 来检索已经加载到 store 中的指定类型的所有记录,而不需要发出HTTP请求:
const blogPosts = this.store.peekAll("blog-post"); // => 没有HTTP请求复制代码
store.findAll() 返回一个满足条件的RecordArray 和 store 的 PromiseArray,store.peekAll 则直接返回 RecordArray。
需要注意的是
RecordArray 并不是一个 JavaScript 数组,它是一个实现 MutableArray 的对象。这是很重要的,因为,例如,如果想按索引检索记录,[] 符号将不起作用,必须使用 objectAt(index) 代替。
查询多条记录
Ember Data 提供了查询满足特定条件的记录的功能。调用 store.query() 将发出一个 GET 请求,并将传递的对象序列化为查询参数。这个方法与 findAll 一样返回一个PromiseArray。
例如,下面在 person 模型中检索名字为 Peter 的人:
// GET to /persons?filter[name]=Peter
this.store
.query("person", {
filter: {
name: "Peter",
},
})
.then(function (peters) {
// 解析检索到的记录
});
查询单条记录
如果使用的适配器支持能够返回单个模型对象的服务器请求,那么 Ember Data 提供了一种便捷的方法 store.queryRecord(),它将返回一个解析该单个记录的 promise 。请求是通过适配器定义的 queryRecord() 方法发出的。
例如,如果服务器 API 为当前登录的用户提供了一个端点app/adapters/user.js :
// GET /api/current_user
{
user: {
id: 6188,
username: "devpoint",
},
};
如果 User 模型的适配器定义了一个针对该端点的 queryRecord() 方法:
import Adapter from "@ember-data/adapter";
import fetch from "fetch";
export default class UserAdapter extends Adapter {
queryRecord(store, type, query) {
return fetch("/api/current_user");
}
}
然后,调用 store.queryRecord() 将从服务器检索该对象:
store.queryRecord("user", {}).then(function (user) {
const username = user.get("username");
console.log(`Currently logged in as ${username}`);
});
与 store.query() 的情况一样,查询对象也可以传递给 store.queryRecord(),适配器的 queryRecord() 可以使用查询对象来限定请求。但是,适配器必须返回单个模型对象,而不是包含一个元素的数组,否则 Ember Data 将抛出异常。
需要注意,Ember 的默认
JSON:API adapter 没有提供直接支持 queryRecord() 所需的方法,因为它依赖于以数组形式返回结果数据的 REST 请求定义。
如果服务器 API 或适配器仅提供数组响应,但又希望只检索一条记录,也可以使用 query() 方法,如下所示:
如果服务器API或适配器仅提供数组响应,但是希望仅检索单个记录,则可以选择使用以下query()方法:
// GET to /users?filter[email]=quintiontang@
const devpoint = store
.query("user", {
filter: {
email: "quintiontang@",
},
})
.then(function (users) {
return users.get("firstObject");
});
创建记录
可以通过调用Store中的createRecord() 方法来创建记录 。
store.createRecord('post', {
title: 'Rails is Omakase',
body: 'Lorem ipsum'
});
可以在控制器和路由中使用store对象this.store。
更新记录
更改Ember Data记录就像设置要更改的属性一样简单:
this.store.findRecord('person', 1).then(function(tyrion) {
// ...after the record has loaded
tyrion.firstName = 'Yollo';
});
持续记录
Ember Data中的记录将按实例持久保存。调用 save() 的任何实例,Model将发出网络请求。
Ember Data会为跟踪每个记录的状态。保存时,这使Ember Data可以将新创建的记录与现有记录区别对待。
默认情况下,Ember Data将POST新创建的记录添加到其类型URL。
let post = store.createRecord('post', {
title: 'Rails is Omakase',
body: 'Lorem ipsum'
});
post.save(); // => POST to '/posts'
后端已存在的记录使用HTTP PATCH动词更新。
store.findRecord('post', 1).then(function(post) {
post.title; // => "Rails is Omakase"
post.title = 'A new post';
post.save(); // => PATCH to '/posts/1'
});
可以通过检查记录的hasDirtyAttributes属性来判断记录是否有尚未保存的未完成的更改。还可以使用changedAttributes()方法查看记录的哪些部分被更改了,以及原始值是什么。changedAttributes返回一个对象,该对象的键是已更改的属性,值是一个值数组[oldValue, newValue]。
person.isAdmin; // => false
person.hasDirtyAttributes; // => false
person.isAdmin = true;
person.hasDirtyAttributes; // => true
person.changedAttributes(); // => { isAdmin: [false, true] }
此时,可以通过保留更改,save()也可以回滚更改。调用 rollbackAttributes() 保存的记录将全部恢复changedAttributes为原始值。如果有记录isNew,它将从Store中删除。
person.hasDirtyAttributes; // => true
person.changedAttributes(); // => { isAdmin: [false, true] }
person.rollbackAttributes();
person.hasDirtyAttributes; // => false
person.isAdmin; // => false
person.changedAttributes(); // => {}
处理Validation错误
如果后端服务器在尝试保存后返回验证错误,则这些错误将在errors模型的属性上可用。这是在博客模板中保存博客帖子时可能显示的错误的方式:
{{#each this.post.errors.title as |error|}}
<div class="error">{{error.message}}</div>
{{/each}}
{{#each this.post.errors.body as |error|}}
<div class="error">{{error.message}}</div>
{{/each}}
Promises
save()返回一个promise,这使得异步处理成功和失败方案变得容易。这是一个常见的模式:
let post = store.createRecord('post', {
title: 'Rails is Omakase',
body: 'Lorem ipsum'
});
let self = this;
function transitionToPost(post) {
self.transitionToRoute('posts.show', post);
}
function failure(reason) {
// handle the error
}
post
.save()
.then(transitionToPost)
.catch(failure);
// => POST to '/posts'
// => transitioning to posts.show route
删除记录
删除记录与创建记录一样简单。在模型的任何实例上调用deleteRecord()。这将记录标记为已删除。然后可以使用save()持久化删除。或者,可以使用destroyRecord方法同时删除和持久化。
let post = store.peekRecord('post', 1);
post.deleteRecord();
post.isDeleted; // => true
post.save(); // => DELETE to /posts/1
});
// OR
post = store.peekRecord('post', 2);
post.destroyRecord(); // => DELETE to /posts/2
});
















