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

时间:2012-06-02 00:39:13

标签: backbone.js

我写的第一次尝试

this.collection.each(function(element){
    element.destroy();
});

这不起作用,因为它类似于Java中的ConcurrentModificationException,其中每个其他元素都被删除。

我尝试在模型中绑定“remove”事件以按照建议Destroying a Backbone Model in a Collection in one step?销毁自身,但如果我在属于集合的模型上调用destroy,则会触发2个删除请求。

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

你认为什么是最简洁的方法来摧毁一系列模型?

由于

7 个答案:

答案 0 :(得分:34)

你也可以使用好的,老式的 pop 就地销毁:

var model;

while (model = this.collection.first()) {
  model.destroy();
}

答案 1 :(得分:24)

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

那真的发生了什么?

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

例如:

console.log(library.models); // [object, object, object, object]

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

library.each(function(model) {
  model.destroy();
});

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

现在,当模型调用destroy时,它也triggers a "destroy" event on the collection,然后remove its reference to the model。在remove内,您会注意到这一点:

this.models.splice(index, 1);

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

只是为了证明:

var list = [1,2];
list.splice(0,1); // list is now [2]

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

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

Uncaught TypeError: Cannot call method 'destroy' of undefined

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

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

为什么呢?根据{{​​3}}:

  

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

那么解决方案是什么?

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

_.each(_.clone(collection.models), function(model) {
  model.destroy();
});

答案 2 :(得分:12)

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

_.invoke(this.collection.toArray(), 'destroy');

答案 3 :(得分:1)

对Sean Anderson的回答。 可以直接访问主干集合数组,因此您可以这样做。

_.invoke(this.collection.models, 'destroy');

或者只是在没有参数的集合上调用reset(),该集合中的模型上的destroy metod将被双触发。

this.collection.reset(); 

http://backbonejs.org/#Collection-models

答案 4 :(得分:0)

这很有意思,我不能使用下划线。

for (var i = this.collection.length - 1; i >= 0; i--)
    this.collection.at(i).destroy();

答案 5 :(得分:0)

我更喜欢这种方法,特别是如果你需要在每个模型上调用destroy,清除集合,而不是调用DELETE到服务器。删除id或设置为idAttribute的任何内容都是允许的。

var myCollection = new Backbone.Collection();
var models = myCollection.remove(myCollection.models);
_.each(models, function(model) {
  model.set('id', null); // hack to ensure no DELETE is sent to server
  model.destroy();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>

答案 6 :(得分:0)

您不需要下划线和for循环。

this.collection.slice().forEach(element => element.destroy());