Backbone.js 在添加事件处理程序中对主干集合进行排序将重新触发添加事件
我有一个集合,它根据模型的属性对自身进行排序,有时我想添加一个模型,然后只计算Backbone.js 在添加事件处理程序中对主干集合进行排序将重新触发添加事件,backbone.js,backbone-events,Backbone.js,Backbone Events,我有一个集合,它根据模型的属性对自身进行排序,有时我想添加一个模型,然后只计算add事件处理程序中的顺序。问题是,当我在add事件处理程序中调用collection.sort()时,出于某种原因,它会再次触发add事件 由于我的add事件进行了一些DOM插入,因此我最终在DOM中得到了重复的项。 到目前为止,我找到的唯一解决方案是,在添加模型或调用u.defer并对集合排序,然后运行任何进一步的代码之前,计算下一个订单 请参阅full fiddle:如果您通读主干网的源代码,则添加函数会将插
add
事件处理程序中的顺序。问题是,当我在add事件处理程序中调用collection.sort()时,出于某种原因,它会再次触发add事件
由于我的add事件进行了一些DOM插入,因此我最终在DOM中得到了重复的项。
到目前为止,我找到的唯一解决方案是,在添加模型或调用u.defer并对集合排序,然后运行任何进一步的代码之前,计算下一个订单
请参阅full fiddle:如果您通读主干网的源代码,则
添加
函数会将插入模型连接到集合中。模型
。在这种情况下,您有四个
因为您没有告诉add
函数为silent,所以它在collection.models中循环并触发插入元素的'add'
事件
但是您在add
处理程序中调用sort
,集合。模型变得不同。当集合在add
函数中执行循环时,插入模型将位于不同的位置,并将再次触发“add”
我不确定这是否有意义,但我认为最好不要在循环过程中重新排列/修改数组。如果通读主干的源代码,则add
函数会将插入模型连接到集合.models
。在这种情况下,您有四个
因为您没有告诉add
函数为silent,所以它在collection.models中循环并触发插入元素的'add'
事件
但是您在add
处理程序中调用sort
,集合。模型变得不同。当集合在add
函数中执行循环时,插入模型将位于不同的位置,并将再次触发“add”
我不确定这是否有意义,但我认为最好不要在循环过程中重新排列/修改数组。关于问题的来源是正确的:在对数组进行迭代时修改数组
您可以从新型号开始使用nOrder:null
:
然后按原样添加
:
for (i = 0, length = this.models.length; i < length; i++) {
if (!cids[(model = this.models[i]).cid]) continue;
options.index = i;
model.trigger('add', model, this, options);
}
然后对集合进行排序:
collection.sort({silent: true});
append: function(m) {
var nOrder = _.max(this.pluck('nOrder')) + 1;
if(m instanceof Backbone.Model)
m.set({ nOrder: nOrder });
else
m.nOrder = nOrder;
this.add(m);
}
这两个动作将事件触发循环中的this.models[0]
移动到this.models[3]
;但是该循环的i
将继续运行,新的this.models[3]
(以前位于0
)将通过,如果(!cids[(model=this.models[i]).cid])
再次测试,然后出现第二个'add'
事件
您可以观看此版本的小提琴作品,了解该系列的阵列在背后的变化:
我认为最简单的解决方案是在集合中添加一个append
方法,在模型上设置适当的nOrder
值,然后将其添加到集合中:
collection.sort({silent: true});
append: function(m) {
var nOrder = _.max(this.pluck('nOrder')) + 1;
if(m instanceof Backbone.Model)
m.set({ nOrder: nOrder });
else
m.nOrder = nOrder;
this.add(m);
}
然后您的'add'
回调可以让nOrder
单独处理并停止对集合排序
演示:
您还可以重写集合的add
方法,但如果您想正确地执行此操作,则此方法要复杂得多。关于问题的来源是正确的:您在对数组进行迭代时正在修改数组
您可以从新型号开始使用nOrder:null
:
然后按原样添加
:
for (i = 0, length = this.models.length; i < length; i++) {
if (!cids[(model = this.models[i]).cid]) continue;
options.index = i;
model.trigger('add', model, this, options);
}
然后对集合进行排序:
collection.sort({silent: true});
append: function(m) {
var nOrder = _.max(this.pluck('nOrder')) + 1;
if(m instanceof Backbone.Model)
m.set({ nOrder: nOrder });
else
m.nOrder = nOrder;
this.add(m);
}
这两个动作将事件触发循环中的this.models[0]
移动到this.models[3]
;但是该循环的i
将继续运行,新的this.models[3]
(以前位于0
)将通过,如果(!cids[(model=this.models[i]).cid])
再次测试,然后出现第二个'add'
事件
您可以观看此版本的小提琴作品,了解该系列的阵列在背后的变化:
我认为最简单的解决方案是在集合中添加一个append
方法,在模型上设置适当的nOrder
值,然后将其添加到集合中:
collection.sort({silent: true});
append: function(m) {
var nOrder = _.max(this.pluck('nOrder')) + 1;
if(m instanceof Backbone.Model)
m.set({ nOrder: nOrder });
else
m.nOrder = nOrder;
this.add(m);
}
然后您的'add'
回调可以让nOrder
单独处理并停止对集合排序
演示:
您还可以覆盖集合的
add
方法,但是如果您想正确地执行,那么这将非常复杂。Ah event storms!你的软件即将消亡的轻轻拍手声。主干网的设计高度依赖于它的设计方式。主要是过度使用事件绑定来附加所有形式的逻辑。@chubbard:这不是一场事件风暴,这是一场“我正在更改我正在迭代的数组”风暴。你在吹毛求疵(可能是开玩笑,但这仍然是一个微不足道的反对)。更改阵列会分派一个事件,这会触发更多逻辑来更改阵列,分派更多事件,依此类推。所有这些都是由自动事件调度和绑定锁定在死亡夹扼流圈中造成的,主干网很乐意提供“最佳实践”。@chubbard:不,这根本不是事件触发事件的问题,甚至不是关闭事件。具体来说,问题是Clay正在修改一些当前正在循环的内容,而事件调度器正在执行循环的事实完全无关紧要。仅仅因为你不喜欢基于事件的系统并不意味着它们总是有错。我的纠正只是:纠正你的错误评论。我不喜欢主干线支持者的方式,或者说没有给出任何真正的方向,使用事件,因为我认为它会造成这样的混乱。一般来说,它不是基于事件的系统。别以为我有偏见。啊,事件风暴!绅士