目前 Emberjs 框架中使用 JSONAPIAdapter 为默认的 adapter,遵循 JSONAPI 的通讯标准。目前本公司也默认使用的是此 adapter,因此一下 api 均是在此基础上。
另如无特殊说明,文内的文件结构均是在 Pods 目录结构下的。
在 Ember Data 中,adapter 决定了如何向后端传递数据,提供了一些能够设置的接口,如 格式化请求的URL ,设置请求的header 等。
在Emberjs 项目中,你能够设置顶层的 application/adapter.js
也能够在每一个对应的 model
(pods文件目录)的文件中建立针对单个model
的adapter:modelName/adapter.js
。其中针对单个的 adapter.js
的优先权大于 application/adapter.js
。git
在 Ember Data 中默认使用的 DS.JSONAPIAdapter
中,若是要请求数据,能够在route.js
中:github
// route.js model() { return this.get('store').findAll('post'); }
上面的请求默认发向的 url 为/posts
,也就是 JSONAPIAdapter 会默认为请求路径转换为复数。ajax
提供了几个默认的请求:json
Action | HTTP Verb | URL |
---|---|---|
Find 1 | GET | /posts/123 |
Find All 2 | GET | /posts |
Update 3 | PATCH | /posts/123 |
Create 4 | POST | /posts |
Delete 5 | DELETE | /posts/123 |
上文也提到了,在使用 JSONAPIAdapter 过程当中,会进行复数的转换,包括对 modelName
也是,会进行转换,好比说 咱们请求:后端
model(){ return this.get('store').findAll('campus'); }
在 JSONAPIAdapter
中会发送请求到 /campus
中,而寻找的 modelName
则是campu
这显然不对,因此咱们须要对特殊字词进行处理。
在 Ember Data 中使用的是 Ember Inflector 控制的复数转换。一样的,咱们也须要对它进行设置(pods目录下):api
// app/app.js import './modules/custom-inflector-rules';
// app/modules/custom-inflector-rules.js import Inflector from 'ember-inflector'; const inflector = Inflector.inflector; // Tell the inflector that the plural of "campus" is "campuses" inflector.irregular('campus', 'campuses'); // Modules must have an export, so we just export an empty object here export default {};
而后能够看到 请求发送的地址是/campuses
,寻找的 modelName
也是 campus
,如今变成正常的了,数据也是能够正常显示的了。数组
JSONAPIAdapter
提供了如下 porperties :缓存
这有篇文章讲的这个属性的使用。下面是具体的使用:
咱们先来看不设置此属性的时候:服务器
// 后端返回的数据 'data': { 'type': 'post', 'id': 'idPost1', 'attributes': { 'title': 'post1', 'content': 'post content' }, 'relationships': { 'comments': { 'data': [ { 'id': 1, 'type': 'comment' }, { 'id': 2, 'type': 'comment' } ] } } }
这是post数据,当咱们请求 post
数据的时候:app
// route.js model() { return this.get('store').findRecord('post', 'idPost1'); }
这时候能够看到 Ember Data 向 mirage 发送了两条请求(须要设置 { async: true }
:
GET '/comments/1' GET '/comments/2'
在将coalesceFindRequests
属性设置为 true
的时候:
// comment/adapter.js import DS from 'ember-data'; export default DS.JSONAPIAdapter.extend({ coalesceFindRequests: true });
能够看到如今只发送一条请求:
GET '/comments?filter[id]=1,2
defaultSerializer
这个属性设置使用的 serializer
:
// post/adapter.js import DS from 'ember-data'; export default DS.JSONAPIAdapter.extend({ defaultSerializer: 'person' });
将使用 person/serializer.js
中的设定对 post
进行设定。
须要注意的是此属性起做用的时候只有在此 model 的serializer.js
以及 application/serializer.js
不存在的时候起做用(Pods目录)。
HTTP 消息头容许客户端和服务器经过 request和 response传递附加信息6。某一些 API 会须要一些请求头,好比如今项目中使用到的 token,就是在每次进行请求的时候都携带这些请求头数据发送给后端服务。通常不在init()
中设置header ,而是将其设为计算属性:
// post/adapter.js headers: computed(function () { return { 'dataType': 'json', 'contentType': 'application/json', 'Content-Type': 'application/json', 'Authorization': `bearer selfToken` }; })
请求头就被改变了。
这样就会在每次请求的时候携带本地的 token。
自定义主机,默认为本地做用域。
顾名思义,定义命名空间的.
// adapter.js namespace: '/api/'
格式化请求的路径:
// router this.get('store').findAll('bjCompany');
若是不在adapter.js
中进行设置,发送的请求是:
GET /bj-companies
也就是默认的转换为中划线以及进行复数化,若是不想进行中划线的转换:
// bj-company/adapter.js import DS from 'ember-data'; import { camelize } from '@ember/string'; import { pluralize } from 'ember-inflector'; export default DS.JSONAPIAdapter.extend({ pathForType(type) { let newType = pluralize(camelize(type)); return newType; // newType: bjCompanies } });
这样就达到了咱们的目的.
对URL 进行格式化,主要是进行复数化,能够经过复写 pathForType()
方法来达到重写 URL 的目的.
JSONAPIAdapter
提供的关于 record 的一些 hook,可让你复写这些hook的逻辑来达到本身的目的,可是通常彻底符合 JSONAPI 的数据规范后,这些基本不用重写.更多关于 Record 的部分请查询 相关API以及其余文档.
这里列举出来 JSONAPIAdapter
中涉及 record 的一些 hook:
fetchRecord
用于生成在客户端生成的 Record 的id.返回的值将分配给 record 的primaryKey
.通常不多使用.好比:
// bj-company/adapter.js generateIdForRecord(store, type, inputProperties) { return 343; }
新建立的 Record 的 id 就会变成 343(这里只是演示做用).
返回 ajax 请求的数据或错误,若是想修改返回的数据规范或错误提示能够在此处进行修改.
不多使用,视具体项目状况而使用.
验证若是是 422 错误,在handleResponse()
返回一个 InvalidError()
的实例.
请求返回成功,相应的status:
(status >= 200 && status < 300) || status === 304;
store使用此方法来肯定在store.findAll
使用缓存的记录数组解析后,存储是否应从新加载记录数组。
默认为 true
.
设为false
以后,带来的效果就是在本地两个页面同时显示同一 model 实例,从一页面跳转到另外一页面的时候不会再次请求数据.
// adapter.js shouldBackgroundReloadAll(store, snapshotArray) { return false; }
注意 这个方法只有在store 返回缓存数据以后才被调用.也就是当第一次请求数据的时候此方法不会被执行.
This method is only checked by the store when the store is returning a cached record array.
与上面同理.
当返回 true 的时候会马上再次请求数据,若是返回false,会当即使用本地缓存.具体使用实例能够查看 文档
与上面同理.
对查询的 参数 进行自定义排列,默认使用的是正序.
为经过 store.createRecord()
建立的本地 record 在进行 record.save()
操做的时候构建 相应的 url
;
其余的api 也相似:
JSONAPIAdapter 的相关API 的分析到此结束.
Written by FrankWang.