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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了更新模型但保留整个Backbone集合相关的知识,希望对你有一定的参考价值。

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

我想只更新“类别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方法中返回数据对象的通知吗?

答案

我会说不要像sync那样使用Khang suggests,并且应该极其谨慎地覆盖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"的启发,我很高兴我们正在使用这本书。

另一答案

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

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

Backbone.sync("update", Notifications);

更多文档here

更新:

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

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

要理解为什么会这样,我建议你阅读Backbone源代码Backbone.sync

以上是关于更新模型但保留整个Backbone集合的主要内容,如果未能解决你的问题,请参考以下文章

保存整个集合的最佳实践?

多个模型子类的 Backbone.js 集合

如何从localStorage集合中删除Backbone模型

模型未在表单提交时更新,使用 Backbone + Stickit

Backbone.js 将两个不同的模型添加到同一个集合中

Backbone.js 模型与集合