英文原版:https://guides.emberjs.com/v2.14.0/models/customizing-adapters/
在Ember Data中,适配器决定了如何持久化发往后端存储的数据,例如URL格式、REST API标头等。(数据本身的格式是由序列化器决定的。) Ember Data默认的适配器对REST API的结构有一些内建的假定。如果你的后端没有遵循这些假定,Ember Data也可以非常容易的通过扩展默认的适配器来被改造符合你自己的规则。
一些导致需要自定义适配器的原因包括:在URL中使用下划线、使用Web本地存储等。
在Ember Data中继承适配器是一种比较普遍的扩展方法。Ember已经为你提供了继承适配器的接口。这将使得代码可测性更高,并且使人更容易理解和降低代码臃肿的程度。
如果你的后端返回的数据结构始终如一,那么你可以在application层面定义适配器。adapter:application 适配器的优先级高于默认的适配器,然而它会被模型的适配器取代。
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
// Application specific overrides go here
});
如果你有个模型,并且这个模型比较独特,那么你可以使用 ember generate adapter adapter-name 命令为你的模型创建一个适配器。例如:运行 ember generate adapter post 命令,将会得到:
app/adapters/post.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
namespace: 'api/v1'
});
默认的,Ember Data内建了若干适配器。 可以通过这些内建的适配器来作为自定义适配器的开端。
- DS.Adapter 是没有什么功能的最基本的适配器。你可以通过它来定义一个与其他适配器完全不同的适配器。
- DS.JSONAPIAdapter 是默认的适配器,它遵循JSON API约定,并通过XHR与后端传递JSON数据。
- DS.RESTAdapter 允许你的store通过XHR来与后端传递JSON数据。在Ember Data 2.0之前,这个是Ember Data的默认适配器。
自定义JSONAPIAdapter
DS.JSONAPIAdapter 适配器定义了一些hook,在与非标准后端协作的时候通常可以继承它们。
URL约定
JSONAPIAdapter非常明智地使用带有模型名称的URL。比如,如果你需要通过ID来获得一个Post记录。
store.findRecord('post', 1).then(function(post) {
});
JSONAPIAdapter会自动的发送一个GET请求到 /posts/1这个地址。
你可以通过下列的Action名称、HTTP 方法和URL来理解Ember 适配器的工作方式:
Action | HTTP Verb | URL |
---|---|---|
Find | GET | /posts/123 |
Find All | GET | /posts |
Update | PATCH | /posts/123 |
Create | POST | /posts |
Delete | DELETE | /posts/123 |
多元化定制
为了在生成路由地址时得到模型名称的复数形式,Ember Data趋向于与Ember Inflector绑定在一起,一个ActiveSupport::Inflector 兼容库用来切换名词的复数与单数形式。不可数或不规则的复数可以通过Ember.Inflector.inflector来指定。一个普遍使用方式是:
app/app.js
// sets up Ember.Inflector
import './models/custom-inflector-rules';
app/models/custom-inflector-rules.js
import Inflector from 'ember-inflector';
const inflector = Inflector.inflector;
inflector.irregular('formula', 'formulae');
inflector.uncountable('advice');
// Meet Ember Inspector's expectation of an export
export default {};
上面的代码会告诉JSON API适配器,请求formula的地址应该是/formulae/1而不是/formulas/1;而对advise的请求,地址应该为/advice/1而不是/advices/1。
当指定复合词的不规则变形规则时,只需要指定最后面的单词或短语。例子,为了指定redCow的复数为redKine或者red-cow的复数为red-kine,只需要指定最后的词语cow和kine即可:
inflector.irregular('cow', 'kine');
自定义请求路径
namespace属性可以用来指定请求时路径的前缀–也称为名称空间:
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
namespace: 'api/1'
});
现在,请求preson数据的地址应该是:http://emberjs.com/api/1/people/1
自定义主机
默认的,适配器将会指向当前的域名。如果你想指向另一个域名,可以通过host属性来改变它:
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
host: 'https://api.example.com'
});
现在,请求preson数据的地址应该是:https://api.example.com/people/1
自定义路径
默认的,JSONAPIAdapter将会通过使用复数及破折号的形式基于模型名称来生成请求路径。如果这个规则不能与你的后端相匹配,那么你可以覆写pathForType方法。
例子,如果你不想用模型名的复数形式,而且你需要用下划线来代替驼峰形式,那么你可以重写pathForType方法:
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
pathForType: function(type) {
return Ember.String.underscore(type);
}
});
那么现在,请求person的地址为/person/1。请求use-profile的地址为/user_profile/1。
自定义请求头
某些接口会要求指定的请求头。你可以通过设置JSONAPIAdapter的headers对象来填入你需要的头值,Ember Data将会在每次ajax请求时都带上设置的头:
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
headers: {
'API_KEY': 'secret key',
'ANOTHER_HEADER': 'Some header value'
}
});
在某些情况下,你的动态header会需要处于Ember的监控范围之外的数据对象(比如,document.cookie)。你可以使用volatile()函数来把计算属性设置为非缓存状态来使得在每次请求时都会触发重新计算。
app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
headers: Ember.computed(function() {
return {
'API_KEY': Ember.get(document.cookie.match(/apiKey\=([^;]*)/), '1'),
'ANOTHER_HEADER': 'Some header value'
};
}).volatile()
});
自己开发适配器
defaultSerializer属性可以用来指定当前适配器的序列化器。这仅仅在当没有为模型指定序列化器或serializer:application未定义的时候使用。
如果你自己开发了一个适配器并且供他人使用,请务必设置此属性来确保在用户没有设置序列化器的时候仍然能正确的执行代码。
app/adapters/my-custom-adapter.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({
defaultSerializer: '-default'
});
公共适配器
如果Ember内建的适配器都没有满足后端的要求。那么你可以在一些社区上寻找可以满足你要求的适配器。下面是一些不错的去处:
本节完