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

Update a model but persist the whole Backbone collection

我的 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;
  },
});

我只想用 active: true 更新 "category 1" 模型(这总是正确的),但将整个集合保留在我的请求负载中,并且不仅仅是改变的模型。我们如何使用 backbone 来实现这一点?

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

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

编辑:

我在下面的回答中使用 实现了这一点。但是我忘了提到我还需要将其他属性与集合一起发送,即上述响应中的 firstNamelastName

我正在重写 parse 方法以将它们包含如下:

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

当我调用 Backbone.sync 时,它仍然只发送负载中的集合。那是因为我在解析方法中只返回来自数据对象的通知吗?

我不确定你想做什么,我觉得这不对。如果只更改一个模型,为什么需要将整个集合发送到服务器?未更改的模型不是已经在服务器上了吗?我认为你应该重新考虑这种方法。

总之如果你真的需要它,这将达到你想要的:

Backbone.sync("update", Notifications);

更多文档here

更新:

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

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

要了解其工作原理,建议您阅读 Backbone 源代码 Backbone.sync

我会说不要像 那样使用 sync 并且 重写 Backbone.sync 函数应该非常小心 因为它被每个模型和集合共享。

虽然它现在适用于您的用例,但它更像是长 运行 中的一个补丁。


the API expects the whole DTO to be sent back in the payload to maintain RESTFul

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

作为对未来读者的参考,制作一个端点来单独管理模型。这是创建 REST API 时要走的路。我在 another answer.

中考虑了 Backbone 的优点和缺点

API is not open to changing their implementation

因为你不能,这意味着 API 响应代表一个模型,而不是一个集合。 Backbone 提供基于RESTful API 其中一个对象应该是一个模型,对象数组应该是一个集合(当接收带有集合的元数据时除外,如页数等)A Backbone 集合由于这个原因没有 save 功能,它不应该一次保存。

在您的情况下,用户模型似乎可以完成这项工作。

请注意,有很多 。这是一个简单的例子。

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();
}

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

在处理大量数据时,这种技术有缺点,无论如何,一次保存所有集合应该暴露出来。 延迟加载分页是在这种情况下提高性能的方法,显然,遵循REST best practices会有很大帮助。

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