【问题标题】:Override Backbone.sync() at Model level to send extra params?在模型级别覆盖 Backbone.sync() 以发送额外的参数?
【发布时间】:2013-05-04 13:37:12
【问题描述】:

老实说,我一直在尝试为模型覆盖 Backbone 的 sync() 方法,我有该函数的签名,并且它被正确触发,但是 我不知道该怎么做放入函数体,以便它对 DELETE 进行默认调用,但带有额外的参数。 即。

class Master.Models.Member extends Backbone.Model
  urlRoot: '/api/members/'

  sync: (method, model, options) ->
    params = _.clone options
    Backbone.sync method, model, params

我这样称呼它:

......
remove: ->
  @model.destroy
    collective_id: the_id

我的意图是将您在此处看到的 collective_id 参数传递给服务器。但即使它在 sync() 的选项哈希中并且我克隆了它,它也不会到达服务器! 如何将额外的参数发送到服务器?

(事实上,到达服务器的唯一信息是模型的 id)

提前致谢!

【问题讨论】:

  • 你的模型可以包含它自己的Sync方法试试看,它接收与Backbone.Sync相同的参数
  • 问题解决了吗?
  • 我今天早上不得不去看医生,我现在就试试答案。会尽快报告,非常感谢!我当然感谢你的好意。

标签: javascript backbone.js coffeescript


【解决方案1】:

参数需要在options.data发送,所以试试:

咖啡脚本

remove: () ->
  @model.destroy 
    data: JSON.stringify
      collective_id: the_id, 
    contentType: 'application/json'

javascript

remove: function() {
  return this.model.destroy({
    data: JSON.stringify({
      collective_id: the_id
    }),
    contentType: 'application/json'
  });
}

【讨论】:

  • 这似乎可以解决问题。我现在正在测试它。我看到的唯一问题是,如果我不在data 上调用 JSON.stringify(),它就不会正确发送。它将在请求中显示为 [Object object],我可以通过 chrome 的网络面板查看
  • 奇怪。你用的是什么版本的BB?它应该只是传递对象。您是否以任何其他方式覆盖了sync?如果是这样,请删除您的 sync 覆盖并使用 Backbone-native 同步。
  • 我正在 JSFiddle 上尝试。结果:i.imgur.com/jzthVqv.png 小提琴:jsfiddle.net/CoryDanielson/YkYA6
  • 查看带注释的源代码,DELETE 请求是唯一没有通过 JSON Stringify 处理其数据的类型。转到backbonejs.org/docs/backbone.html,然后按 CTRL + F 获取文本“确保我们有适当的请求数据”。向右看,你会看到一大块处理 options.data 的代码,仅用于创建、更新和修补。
  • 是的:backbonejs.org/docs/backbone.html#section-139 。每天学些新东西!对于 DELETE,您必须自己 JSON.stringify
【解决方案2】:

当您调用 .destroy()、.fetch() 或 .save() 时,它们都会调用 Model.sync,而后者仅调用 Backbone.sync。这是一个代理功能。这旨在为修改单个模型或从该模型扩展的任何模型的 AJAX 行为提供一个很好的钩子。

  • 解决方案 1:将 Global Backbone.sync 覆盖为 JSON.stringify 并在您指定要与删除请求一起发送的数据时修改 contentType
    • 优点:您可以调用model.destroy() 并可选择传入options 参数
  • 解决方案 2 - 覆盖 Model.sync 方法。
    • 优点:覆盖仅影响单个模型。孤立的变化。
    • 缺点:所有希望删除数据的模型都需要从正确的“基础模型”扩展
  • 解决方案 3 - 不要覆盖任何内容,并使用所有 stringifycontentType 内容显式调用 model.sync。
    • 优点:非常孤立的更改,不会影响任何其他模型。如果您要与大型代码库集成,这很有用。

[Solution 1] - Global Override of Backbone.sync (this will affect all models)

javacript 版本

var oldBackboneSync = Backbone.sync;
Backbone.sync = function( method, model, options ) {
    // delete request WITH data
    if ( method === 'delete' && options.data ) {
        options.data = JSON.stringify(options.data);
        options.contentType = 'application/json';
    } // else, business as usual.
    return oldBackboneSync.apply(this, [method, model, options]);
}

用法

var model, SomeModel = Backbone.Model.extend({ /* urlRoot, initialize, etc... */});
model = new SomeModel();
model.destroy({
    data: {
        /* data payload to send with delete request */
    }
});

[Solution 2] - Override Backbone.destroy on a base model and extend other models from that.

覆盖

// Create your own 'enhanced' model 
Backbone.EnhancedModel = Backbone.Model.extend({
    destroy: function( options ) {
        if ( options.data ) {
            // properly formats data for back-end to parse
            options.data = JSON.stringify(options.data);
        }
        // transform all delete requests to application/json
        options.contentType = 'application/json';
        Backbone.Model.prototype.destroy.call(this, options);
    }
});

用法

var model, SomeModel = Backbone.EnhancedModel.extend({ /* urlRoot, initialize, etc... */})
model = new SomeModel();
SomeModel.destroy({
    data: {
        /* additional data payload */
    }
}); 

[Solution 3] - Call .destroy() with correct parameters.

如果使用销毁请求发送数据是一个孤立的事情,那么这是一个适当的解决方案。

调用model.destroy() 时,传入datacontentType 选项,如下所示:

javascript 版本/用法

var additionalData = { collective_id: 14 };
model.destroy({
    data: JSON.stringify(additionalData),
    contentType: 'application/json'
});

“问题”(使用 Backbone,而不是解决方案):

Backbone.js 假设 (view source) 删除请求没有有数据负载。

// delete methods are excluded from having their data processed and contentType altered.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
      params.contentType = 'application/json';
      params.data = JSON.stringify(options.attrs || model.toJSON(options));
}

在他们假定的 RESTful API 调用中,唯一需要的数据是应附加到 urlRoot 属性的 ID。

var BookModel = Backbone.Model.extend({
    urlRoot: 'api/book'
});
var book1 = new BookModel({ id: 1 });
book1.destroy()

删除请求会像这样发送

DELETE => api/book/1
contentType: Content-Type:application/x-www-form-urlencoded; charset=UTF-8

【讨论】:

  • 唷。我几乎要放弃了:p
  • 请注意,您在解决方案 #1 和 #2 中拼错了“application/json” - 您错过了“i”。用复制/粘贴抓住了我,我得到一个 .Net 服务器错误:不支持的媒体类型
  • When you call .destroy(), .fetch() or .save() they all eventually call Backbone.sync. They don't call Model.sync. Model.sync is ONLY called if you explicitly call it. 我不同意。截至 2014 年 6 月 23 日的 annotated source 似乎暗示 Model.save 调用 this.sync,默认情况下它是 Backbone.sync 的代理,但可以为每个 Model 实例覆盖。
  • @Jeremy.S 我相信
  • @CoryDanielson:解决方案 3 有效,但它在 request.payload 中 :) 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 2014-11-05
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多