如何为 ember.js 创建自定义适配器? [英] How do you create a custom adapter for ember.js?

查看:22
本文介绍了如何为 ember.js 创建自定义适配器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算使用 ember.js,但是我的 REST api 与打包的 REST 适配器并不完全一致.我想覆盖" find 并能够将我自己的 ajax 放入其中.我不喜欢 ember findAll 如何在没有分页选项的情况下检索我的所有文档,以便与其他查询参数一起使用 - 这就是我想编写自己的 ajax 的原因.我一直找不到关于我将如何执行此操作的任何文档.

解决方案

对于 Ember 数据

这是 Ember Data 1.0 beta 9 的最新版本.

扩展 Ember 数据适配器之一.使其网站范围广:

App.ApplicationAdapter = DS.RESTAdapter.extend(....

使其特定于模型:

App.FooAdapter = DS.RESTAdapter.extend(...

然后您将定义要覆盖的实现.您始终可以选择调用 this._super 并恢复到基本实现.例如

App.NotesAdapter = DS.RESTAdapter.extend({查找:函数(存储,类型,ID){id =foo"+ 身份证;返回 this._super(store, type, id);}});

或者你可以完全覆盖实现:

App.NotesAdapter = DS.RESTAdapter.extend({查找:函数(存储,类型,ID){//在这里做你的事返回 this.ajax(this.buildURL(type.typeKey, id), 'GET');},findAll:函数(存储,类型,因为令牌){//在这里做你的事无功查询;如果(因为令牌){查询 = { 因为:因为令牌 };}返回 this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });},findQuery:函数(存储,类型,查询){//在这里做你的事返回 this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });},findMany:函数(存储,类型,ID,所有者){返回 this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });},.....});

要查看完整的 api,您可以覆盖:http://emberjs.com/api/data/classes/DS.RESTAdapter.html

序列化器

通常更重要的是滚动您自己的序列化程序,用于按摩数据以适合您的休息端点.以下是转换文档 https://github.com/emberjs/data 中的一些有用信息/blob/master/TRANSITION.md .

简短的版本是,一旦 Ajax 请求完成,生成的负载将通过以下钩子发送:

  1. 如果原始请求是针对单个记录(如 find/save)或 extractArray,如果原始请求是针对记录数组(如 findAll/findQuery),则负载被发送到 extractSingle
  2. 这些方法的默认行为是将有效负载的顶层拆分为多个较小的记录.
  3. 将这些较小的记录中的每一个发送到规范化,这可以一次对记录进行规范化.
  4. 最后,可以对特定类型的记录进行特殊规范化.

<前>App.PostSerializer = DS.RESTSerializer.extend({提取单:功能(存储,类型,有效载荷,ID){//按摩this._super(store, type, payload, id);},提取数组:函数(存储,类型,有效载荷){//按摩this._super(store, type, payload);},规范化:函数(类型,哈希,属性){//按摩this._super(type, hash, property);}});

  • 当您的有效负载顶层的组织方式与 Ember Data 预期的不同时,请使用 extractSingle 和 extractArray
  • 如果有效载荷中的所有子哈希都可以以相同的方式标准化,则使用 normalize 来标准化子哈希.
  • 使用 normalizeHash 规范化特定的子哈希.
  • 如果您覆盖了 extractSingle、extractArray 或 normalize,请确保调用 super 以便调用链的其余部分.

自己动手

App.FooAdapter = Ember.Object.extend({查找:函数(id){返回 $.getJSON('http://www.foolandia.com/foooo/' + id);}});

然后从您的路线,或任何地方

App.FooRoute = Ember.Route.extend({模型:函数(){var 适配器 = App.FooAdapter.create();返回适配器.find(1);}});

现在我个人将适配器注入路由只是为了让我的生活更轻松:

App.initializer({名称:fooAdapter",初始化:函数(容器,应用程序){application.register("my:manager", application.FooAdapter);application.inject("controller", "fooAdapter", "my:manager");application.inject("route", "fooAdapter", "my:manager");}});

然后在路线上你可以更懒惰并做:

App.FooRoute = Ember.Route.extend({模型:函数(){返回 this.fooAdapter.find(1);}});

示例:http://emberjs.jsbin.com/OxIDiVU/676/edit

您可以在没有 Ember 数据的情况下阅读有关 Ember 的更多信息:没有 Ember 数据的 Ember

I'm planning on using ember.js, however my REST api doesn't exactly align with the packaged REST Adapter. I would like to "override" find and be able to put my own ajax in it. I dislike how an ember findAll retrieves all my documents with no options for pagination, so that along with other query parameters would be useful --which is why I want to write my own ajax. I've been unable to find any documentation on how I would go about doing this.

解决方案

For Ember Data

This is up to date as of Ember Data 1.0 beta 9.

Extend one of the Ember Data Adapters. To make it site wide:

App.ApplicationAdapter = DS.RESTAdapter.extend(....

To make it model specific:

App.FooAdapter = DS.RESTAdapter.extend(...

Then you will define the implementation you'd like to override. You always have the option to call this._super and revert to the base implementation. e.g.

App.NotesAdapter = DS.RESTAdapter.extend({
  find: function(store, type, id) {
    id = "foo" + id;
    return this._super(store, type, id);
  }
});

Or you can completely override the implementation:

App.NotesAdapter = DS.RESTAdapter.extend({
  find: function(store, type, id) {
    // Do your thing here
    return this.ajax(this.buildURL(type.typeKey, id), 'GET');
  },

  findAll: function(store, type, sinceToken) {
    // Do your thing here
    var query;

    if (sinceToken) {
      query = { since: sinceToken };
    }

    return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
  },

  findQuery: function(store, type, query) {
    // Do your thing here
    return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
  },

  findMany: function(store, type, ids, owner) {
    return this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });
  },
   .....
});

To see the complete api you can override see: http://emberjs.com/api/data/classes/DS.RESTAdapter.html

Serializer

Often more important will be rolling your own serializer for massaging the data to fit your rest endpoint. Here's some useful information from the transition document https://github.com/emberjs/data/blob/master/TRANSITION.md .

The short version is that once an Ajax request has completed, the resulting payload is sent through the following hooks:

  1. The payload is sent to extractSingle if the original request was for a single record (like find/save) or extractArray if the original request was for an Array of records (like findAll/findQuery)
  2. The default behavior of those methods is to pull apart the top-level of the payload into multiple smaller records.
  3. Each of those smaller records is sent to normalize, which can do normalization a record at a time.
  4. Finally, specific types of records can be specially normalized.

    App.PostSerializer = DS.RESTSerializer.extend({
      extractSingle: function(store, type, payload, id) {
        // massage
        this._super(store, type, payload, id);
      },
      extractArray: function(store, type, payload) {
        // massage
        this._super(store, type, payload);
      },
      normalize: function(type, hash, property) {
        // massage
        this._super(type, hash, property);
      }
    });

  • use extractSingle and extractArray when the top-level of your payload is organized differently than Ember Data expects
  • use normalize to normalize sub-hashes if all sub-hashes in the payload can be normalized in the same way.
  • use normalizeHash to normalize specific sub-hashes.
  • make sure to call super if you override extractSingle, extractArray or normalize so the rest of the chain will get called.

Rolling your own

App.FooAdapter = Ember.Object.extend({
  find: function(id){
    return $.getJSON('http://www.foolandia.com/foooo/' + id);
  }
});

Then from your route, or wherever

App.FooRoute = Ember.Route.extend({
  model: function(){
    var adapter = App.FooAdapter.create();
    return adapter.find(1);
  }
});

Now personally I'd inject the adapter onto the routes just to make my life easier:

App.initializer({
    name: "fooAdapter",

    initialize: function (container, application) {
        application.register("my:manager", application.FooAdapter);
        application.inject("controller", "fooAdapter", "my:manager");
        application.inject("route", "fooAdapter", "my:manager");
    }
});

Then on the route you could be lazier and do:

App.FooRoute = Ember.Route.extend({
  model: function(){
    return this.fooAdapter.find(1);
  }
});

Example: http://emberjs.jsbin.com/OxIDiVU/676/edit

You can read more about Ember without Ember Data: Ember without Ember Data

这篇关于如何为 ember.js 创建自定义适配器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆