更新模型但保留整个Backbone集合

时间:2017-12-16 00:28:57

标签: javascript backbone.js backbone-collections backbone-model

我的API响应:

{
  firstName: '',
  lastName: '',
  notifications: [
    {
      category: '1',
      subcategory: '',
      source: '',
      optInDate: '',
      optOutDate: '',
      active: ''
    },
    {
      category: '2',
      subcategory: '',
      source: '',
      optInDate: '',
      optOutDate: '',
      active: ''
    }
  ]
}

响应的相应Backbone实现是:

var Notification = Backbone.Model.extend({
  initialize: function (args) {  },
});

var Notifications = Backbone.Collection.extend({
  model: Notification,
  url: '/xyz/abc',

  parse: function (data) {
    return data.notifications;
  },
});

我想只更新“category 1”模型(这始终是真的),而是active: true,但是将整个集合保存在我的请求有效负载中,而不仅仅是更改后的模型。我们如何通过骨干实现这一目标?

我已尝试获取该特定模型并执行model.set({active: true})并调用model.save()但仅将该模型发送到服务器。

我需要将整个响应与更新的模型一起保存回服务器。

修改

我在下面的回答中用@Khang's help实现了这一点。但是我忘了提到我需要发送其他属性以及集合,即上述响应中的firstNamelastName

我正在覆盖parse方法以包含它们,如下所示:

parse: function(data) { 
  this.firstName = data.firstName; 
  this.lastName = data.lastName; 
  return data.notifications; 
} 

当我呼叫Backbone.sync时,它仍然只在有效负载中发送集合。那是因为我只是在parse方法中返回数据对象的通知吗?

2 个答案:

答案 0 :(得分:3)

我要说不要像Khang suggests那样使用sync而应该非常谨慎地覆盖Backbone.sync功能,因为它是每个模型和集合共享。

虽然它现在适用于您的用例,但从长远来看,它更像是一个补丁。

  

API期望将整个DTO发送回有效负载以维护RESTFul

如果API真的是RESTful,它将提供一个端点来单独管理通知。

作为对未来读者的参考,建立一个端点来单独管理模型。这是创建REST API时的方法。我在another answer中考虑了Backbone的这种技巧的优缺点。

  

API无法更改其实施

因为你不能,这意味着 API响应代表模型,而不是集合。 Backbone提供基于RESTful API的预定义行为,其中对象应该是模型,数组对象应该是一个集合(例外情况是接收带有像页数等集合的元数据时)。由于这个原因,Backbone Collection没有save函数,因此不应该一次性保存。

在您的情况下,看起来用户模型可能会完成这项工作。

请注意,有很多alternatives to implement a collection within a model。这是一个简单的例子。

var UserModel = Backbone.Model.extend({
    urlRoot: '/xyz/abc',
    initialize: function(attrs, options) {
        // init a collection within the model
        this.notifications = new Notifications((attrs || {}).notifications);
        // update the collection whenever the model is synced.
        this.listenTo(this, 'sync', this.onSync());
    },

    // Useful abstraction that doesn't interfere with the normal use-case
    saveNotifications: function() {
        return this.save({
            notifications: this.notifications.toJSON()
        }, { patch: true });
    },

    onSync: function() {
        this.notifications.reset(this.get('notifications'));
    }
});

您可以像使用任何其他

一样使用该模型
var user = new UserModel({ id: 'user-id-1' });
user.fetch();

当您需要通知时,它们已经在一个方便的集合中可用。

var notif = user.notifications.findWhere({ category: '1' });
if (notif) {
    notif.set({ active: true });
    user.saveNotifications();
}

用户模型上的sync等主干事件和通知集合上的reset将正确触发。

当处理大量数据时,这种技术存在缺点,无论如何都要立即保存集合。 延迟加载分页是在这种情况下提高性能的方法,显然,REST best practices后面会有很多帮助。

在我们公司,我们的API深受"Build APIs you won't hate"的启发,我很高兴我们正在使用这本书。

答案 1 :(得分:0)

我不确定你要做什么,这对我来说似乎不对。如果只有一个模型发生变化,为什么需要将整个集合发送到服务器? Aren已经在服务器上的未更改的模型?我认为你应该重新考虑这种方法。

无论如何,如果你真的需要它,这将实现你想要的:

Backbone.sync("update", Notifications);

更多文档here

<强>更新

如果每次收集sync时都有许多额外数据要发送,则可以覆盖sync方法以使集合具有自定义同步行为。否则,您可以在需要时使用options.attrs获取自定义数据:

Backbone.sync("update", Notifications, {
    attrs: {
        data: Notifications.toJSON(),
        firstName: 'foo',
        lastName: 'bar',
    }
});

要了解其原因,我建议您阅读Backbone源代码Backbone.sync