【问题标题】:Backbone.js firing Collection change event multiple timesBackbone.js 多次触发 Collection 更改事件
【发布时间】:2012-10-24 22:02:21
【问题描述】:

在 Backbone.js 视图之一中,我正在使用 this.model.set( { read: true } ); 更新当前模型(消息实例)的“读取”属性。我验证了这个命令只执行一次(我知道“鬼事件”)。正如您在下面看到的,我将集合配置为触发更新事件,其中整个集合被保存到变量中。 不幸的是,saveToVar 函数被调用了 3 次而不是 1 次!此外,第一次调用saveToVarthis 正确包含所有集合的模型,而第二次和第三次this 只有一个模型,即我进行更新的模型。 我逐条追踪所有内容,但我不知道为什么会发生这种情况。

window.Message = Backbone.Model.extend({

});

window.MessageCollection = Backbone.Collection.extend({

model: Message,

initialize: function()
{
    this.on("change", this.saveToVar);
},

saveToVar: function(e)
{
    App.Data.Messages = this.toJSON();
    return;
}

});

【问题讨论】:

  • 我将代码粘贴到 jsfiddle.net 中,但由于某种原因我无法运行它?实际上,以前从未使用过它。 link
  • 我也挖得更深了,似乎saveToVar: function(model) { App.Data.Messages = model.collection.toJSON();} 是一种解决方法。也许集合中的this 指的是模型?
  • 但在这里,事件又被触发了 3 次!
  • 您需要在 jsfiddle.net 上包含 backbone.jsunderscore.jsjquery.js,而不仅仅是 underscore.js。看看我的回答中小提琴上的 Manage Resources 面板,你会看到如何包含你需要的任何外部 JS 和 CSS 资源。

标签: backbone.js backbone-events


【解决方案1】:

在您的 jsfiddle 中,您正在这样做:

App.Collections.message = new MessageCollection([ ... ]);
var elements = App.Collections.message.where({ id: 4 });
var item = new MessageCollection(elements);

您的where 调用将返回message 集合中的模型,而不是这些模型的副本,而是与message 中完全相同的模型对象。现在您有两个对 id: 4 模型的引用:

  1. 原来埋在里面的那个App.Collections.message
  2. elements[0] 中的那个。

这两个引用都指向同一个对象。然后将elements 添加到另一个MessageCollection。现在你有这样的东西:

App.Collections.message.models[3]    item.models[0]
                               |                 |
                               +--> [{id: 4}] <--+

这两个集合都将收到关于 id: 4 模型自 collections listen to all events on their members 以来的更改事件的通知:

为方便起见,在集合中的模型上触发的任何事件也将直接在集合上触发。

您的集合本身会监听 "change" 事件:

initialize: function()
{
    this.on("change", this.saveToVar);
}

所以当你这样做时:

this.model.set({ read: true });

在您看来,两个集合都会收到通知,因为该模型恰好在两个集合中。

如果我们将您的事件处理程序更改为如下所示:

saveToVar: function() {
    console.log(_(this.models).pluck('cid'));
}

然后您会看到相同的cid(Backbone 生成的唯一标识符)出现在两个集合中。您还可以为每个集合附加一个随机数,看看您在saveToVar 中得到了什么:http://jsfiddle.net/ambiguous/mJvJJ/1/

您可能不应该在两个系列中拥有一个模型。您可能不应该有两个相同模型的副本,因此在创建item 之前克隆elements[0] 也可能不是一个好主意。您可能需要重新考虑您的架构。

【讨论】:

  • 感谢您的帮助!我可以看到 .where() 正在复制模型,而 .get() 实际上只是一个参考。有没有办法使用 .where() 仅获取集合中模型子集的引用?
  • @hofimax:你可以得到一个数组,但不能得到另一个集合。
猜你喜欢
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 2012-05-15
  • 2015-03-24
  • 1970-01-01
  • 2015-02-19
  • 2020-01-31
相关资源
最近更新 更多