2014-04-15 77 views
1

这个应该很简单,但不是,它让我很头疼。骨干视图collection.each()bug?

我复制/粘贴一个相当简单的“Hello骨干”的代码,并简化了它多一些,得到这个:

(function($){ 
    var Item = Backbone.Model.extend({ 
    defaults: { 
     part1: 'hello', 
     part2: 'world' 
    }, 

    initialize: function() { 
     //console.log("initialize item"); 
    } 
    }); 

    var List = Backbone.Collection.extend({ 
    model: Item, 

    initialize: function() { 
     //console.log("initialize list"); 
    } 
    }); 

    var ListView = Backbone.View.extend({ 
    //el: $('body'), // el attaches to existing element 

    initialize: function(){ 
     _.bindAll(this, 'render'); // every function that uses 'this' as the current object should be in here 

     this.collection = new List(); 

     this.render(); 
    }, 
    render: function(){ 
     //console.log("listview render"); 
    }, 
    }); 

    var listView = new ListView(); 

    var item1 = new Item(); 
    listView.collection.add(item1); 

    console.dir("Emptying collection..."); 
    listView.collection.each(function (item) { 
    console.dir("Removing model cid:" + item.cid); 
    listView.collection.remove(item); 
    }) 

    var item2 = new Item(); 
    listView.collection.add(item2); 

    var item3 = new Item(); 
    listView.collection.add(item3); 

    console.dir("Emptying collection..."); 
    listView.collection.each(function (item) { 
    console.dir("Removing model cid:" + item.cid); 
    listView.collection.remove(item); 
    }) 

    console.log(listView.collection.length); 
})(jQuery); 

第一部分实际上是一些骨干样板东西,最后一个应该:

  • 一个模型添加到收藏
  • 明确收集
  • 两款车型添加到收藏
  • 明确收集

最后,listView.collection.length应该是0,但它不是。 还有一个模型。

我从控制台日志中看到了什么,该listView.collection.each(function (item) { ... })没有做它应该做的事情,因为只有一个项目在第二收集迭代删除,而不是项目。

那么,我做错了什么或有什么地方有bug?

更新:这里的jsfiddle

+0

第一件错误的是你的小提琴。它没有建立依赖关系。 –

+0

@StephenThomas查找外部资源。有jQuery,Underscore和Backbone。也许有一些我错过了? – OzrenTkalcecKrznaric

+0

啊对。错过了他们 –

回答

1

你改变元素(listView.collection.remove(item))的列表在遍历它,这通常会导致坏事™这里有一个简单的测试案例:http://jsfiddle.net/nikoshr/Xx9uw/

之前克隆您的机型列表除去它们:

_.each(_.clone(listView.collection.models), function (item) { 
    console.log("Removing model cid:" + item.cid); 
    listView.collection.remove(item); 
}); 

http://jsfiddle.net/nikoshr/Xx9uw/2/

或者使用collection.reset

listView.collection.reset(); 

http://jsfiddle.net/nikoshr/Xx9uw/3/

+0

准确,不重复的收集删除一次又一次。令我惊讶的是,多年来我用不同的语言来犯同样的错误:D – OzrenTkalcecKrznaric

0

的问题是,你永远创建集合。

var list = new List(); var listView = new ListView({collection: list});

+1

我绝对在ListView.initialize()中初始化集合。 – OzrenTkalcecKrznaric

0

我看到@ nikoshr的答案的那一刻,我知道我是一个傻瓜。再次。我在不同的语言,C/C++(通常产生ye-olde-segfault),Java,C#等等现在重复同样的错误,现在是JS/BB。

该死的。

除了nikoshr的答案,我发现这个基于集合的解决方案,可避免传统迭代(在C#中可以使用用于该目的LINQ扩展):

this.collection 
    .forEach(function (item) { 
    item.destroy() 
    }); 

便利,下划线为您提供了一个选项,过滤掉你真正需要的模型:

this.collection 
    .where({ YourAttribute: YourValue, YourOtherAttribute: YourOtherValue }) 
    .forEach(function (item) { 
    item.destroy() 
    });