最简洁的方法来销毁Backbone中集合中的每个模型?

Hen*_*nry 17 backbone.js

在我写的第一次尝试

this.collection.each(function(element){
    element.destroy();
});
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为它类似于ConcurrentModificationExceptionJava中删除所有其他元素.

我尝试在模型中绑定"删除"事件来销毁自己,因为建议在一个步骤中销毁集合中的骨干模型?,但如果我在属于集合的模型上调用destroy,则会触发2个删除请求.

我查看了下划线文档,看不到each()向后循环的变体,这将解决删除每个元素问题.

你会建议什么是最简洁的方法来摧毁一系列模型?

谢谢

rjz*_*rjz 34

你也可以使用一个好的,老式的 流行的 破坏就地:

var model;

while (model = this.collection.first()) {
  model.destroy();
}
Run Code Online (Sandbox Code Playgroud)

  • 销毁骨干模型将触发DELETE api调用 - 抛出"A"url"属性或函数必须指定`错误.你需要首先`model.id = null`然后你可以`model.destroy()' (4认同)

lin*_*les 24

我最近也遇到了这个问题.看起来你解决了这个问题,但我认为更详细的解释也可能对那些想知道为什么会发生这种情况的人有用.

那真的发生了什么?

假设我们有一个模型(书籍)的集合(库).

例如:

console.log(library.models); // [object, object, object, object]
Run Code Online (Sandbox Code Playgroud)

现在,让我们使用您的初始方法浏览并删除所有书籍:

library.each(function(model) {
  model.destroy();
});
Run Code Online (Sandbox Code Playgroud)

each是一个下划线方法,混合到Backbone集合中.它使用对其models(library.models)的集合引用作为这些各种下划线集合方法的默认参数.好的,当然.这听起来很合理.

现在,当模型调用时destroy,它也会在集合上触发"destroy"事件,然后删除对模型的引用.在里面remove,你会注意到这一点:

this.models.splice(index, 1);
Run Code Online (Sandbox Code Playgroud)

如果您不熟悉splice,请参阅文档.如果你是,你可能会发现为什么这是有问题的.

只是为了证明:

var list = [1,2];
list.splice(0,1); // list is now [2]
Run Code Online (Sandbox Code Playgroud)

这将导致each循环跳过元素,因为它对模型对象via的引用models正在被动态修改!

现在,如果你使用JavaScript <1.6,那么你可能会遇到这个错误:

Uncaught TypeError: Cannot call method 'destroy' of undefined
Run Code Online (Sandbox Code Playgroud)

这是因为在下划线实现中each,如果forEach缺少本机,它将依赖于它自己的实现.如果你在迭代中删除一个元素,它会抱怨它,因为它仍然试图访问不存在的元素.

如果本机forEach存在,那么它将被替代使用,你根本不会得到错误!

为什么?根据文件:

如果更改或删除了数组的现有元素,则传递给回调的值将是每次访问它们时的值; 不会访问已删除的元素.

那么解决方案是什么?

collection.each如果您要从集合中删除模型,请不要使用.使用一种方法,允许您处理包含模型引用的新数组.一种方法是使用下划线clone方法.

_.each(_.clone(collection.models), function(model) {
  model.destroy();
});
Run Code Online (Sandbox Code Playgroud)


Sea*_*son 13

我在这里有点晚了,但我认为这也是一个非常简洁的解决方案:

_.invoke(this.collection.toArray(), 'destroy');
Run Code Online (Sandbox Code Playgroud)

  • 如果我们在去的时候破坏元素,那么集合迭代很可能不能正常工作?无论哪种方式 - "toArray"仍然是一个很好,整洁的答案.如果它有效,那就放手吧!:^) (2认同)