Ember Data 之记录查询

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 前面在《Ember.js 项目开发之 Ember Data》介绍了Ember Data 和 《Ember Data 之模型定义》,本文将继续介绍记录操作。

前面在《Ember.js 项目开发之 Ember Data》介绍了Ember Data 和 《Ember Data 之模型定义》,本文将继续介绍记录操作。

记录检索

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() 返回一个满足条件的RecordArraystorePromiseArraystore.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@gmail.com
const devpoint = store
    .query("user", {
        filter: {
            email: "quintiontang@gmail.com",
        },
    })
    .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
});


相关文章
|
6月前
egg.js 24.13sequelize模型-字段限制排序分页
egg.js 24.13sequelize模型-字段限制排序分页
76 1
egg.js 24.13sequelize模型-字段限制排序分页
|
1月前
|
JavaScript
el-table 使用了 修改行使用了v-model双向绑定 如何记录修改前的数据
el-table 使用了 修改行使用了v-model双向绑定 如何记录修改前的数据
96 1
|
2月前
|
JavaScript 前端开发 UED
组件库实战 | 用vue3+ts实现全局Header和列表数据渲染ColumnList
该文章详细介绍了如何使用Vue3结合TypeScript来开发全局Header组件和列表数据渲染组件ColumnList,并提供了从设计到实现的完整步骤指导。
|
JavaScript 前端开发 API
Angular1.4.6框架简单读取数据库信息并渲染完成news新闻文章列表以及detail详情页功能(小试牛刀)
Angular1.4.6框架简单读取数据库信息并渲染完成news新闻文章列表以及detail详情页功能(小试牛刀)
|
JavaScript UED
Vue3+TS+Vant3——增删改input和通过双页面进行增删改操作
增删改input和通过双页面进行增删改操作
191 0
|
移动开发 小程序 JavaScript
微信小程序:uni-app列表数据渲染子组件修改数据sync/v-model无效的问题
微信小程序:uni-app列表数据渲染子组件修改数据sync/v-model无效的问题
442 0
|
JSON JavaScript 数据格式
VUE element-ui之jspreadsheet-ce在线表格数据json序列化(excel数据同步为相应key:value,并过滤掉为空的数据,未输入的行)
VUE element-ui之jspreadsheet-ce在线表格数据json序列化(excel数据同步为相应key:value,并过滤掉为空的数据,未输入的行)
586 0
VUE element-ui之jspreadsheet-ce在线表格数据json序列化(excel数据同步为相应key:value,并过滤掉为空的数据,未输入的行)
|
中间件
【Node.js+koa--后端管理系统】设计评论发布、修改、查询、删除接口
【Node.js+koa--后端管理系统】设计评论发布、修改、查询、删除接口
233 0
【Node.js+koa--后端管理系统】设计评论发布、修改、查询、删除接口
|
SQL PHP
Thinkphp查询is null数据
Thinkphp查询is null数据
452 0
|
缓存 资源调度
[项目篇]vue3+ts 封装request请求,storage缓存,config请求信息抽离 - 第二天
[项目篇]vue3+ts 封装request请求,storage缓存,config请求信息抽离 - 第二天