在视图中从模型内的集合中删除项目时遇到一些问题。基本上模型/集合结构如下:
基本上,当我尝试从子项视图中的子项集合中删除项目时,它实际上从集合中删除了正确的项目。然而,当我来坚持主模型时,项目似乎仍然在集合中 这就是我的观点的结构:
主视图插入主模型所需的DOM节点,主模型为项目模型等创建新视图。所有视图都将主模型作为模型选项,如下所示:
new App.Views.MainModelView({
model : this.model,
el : $('#nodeID')
})
唯一的区别在于子项目模型视图的创建,其中,由于视图和模板的可用性,我仍然传入主模型,但是我也传入项目集合中的项目目前正在修改中。看起来像这样:
new App.Views.ItemView({
model : this.model,
item : this.selectedItem,
el : $('#nodeID')
});
在子项目的视图init方法中,我执行以下操作:
this.item = (this.options.item) ? this.options.item : this.model;
要从子项集合中删除子项目,我会这样做:
removeSubItem : function(e) {
// get the id of the sub-item to be removed
var id = $(e.target).closest('tr').attr('data-id');
if (!id) throw "Could not retrieve data id";
// retrieve the sub-item from the collection
var subItem = this.item.subItems.get(id);
// remove the sub-item from the collection
this.item.subItems.remove(subItem);
},
正如我之前所说,当我删除子项并检查由视图修改的集合时,我可以看到子项已从集合中删除,但是我将主模型保留为已删除的子项重新出现。这让我相信,沿线的某个地方可能会克隆子项集合,这可以解释子项目的突然再现。
我知道这是一个相当具体的问题,我不确定是否有可能通过我在这里提供的问题找到问题的原因,如果您需要更多信息,请告诉我。
感谢您的帮助,
文森特
==========编辑============
为了回答下面的一些问题,让我概述一下我遇到这个问题的范围:
如果我控制台在SubItem视图中记录this.item.subItems集合,则在调用removeSubItem之后,我可以看到已成功删除SubItem模型的实例。 在我调用主模型上的save方法之前,我在控制台上记录了toJSON函数的返回。此时我遇到的问题是先前删除的实例在集合中“后退”。我一直在使用Wireshark和Google Chrome的开发者控制台监控客户端和服务器之间的流量,并且没有要求服务器刷新任何模型。
SubItem集合的toJSON方法如下所示:
toJSON : function() {
App.log(["SubItem::collection::toJSON", this], "info");
var json = {};
// make sure the key for each SubItem is the primary key
this.each(function(subItem) {
json[subItem.get('id')] = subItem.toJSON();
});
return json;
}
答案 0 :(得分:2)
Backbone.js对嵌套集合/模型的支持不存在,并且它们不提供保存支持(请参阅http://documentcloud.github.com/backbone/#FAQ-nested)。您必须在具有子集合的任何模型上覆盖toJSON。我已经遇到过这种情况一百万次了。如果您有类似的东西(在coffeescript中):
class MainModel extends Backbone.Model
itemCollection: ->
@_itemCollection ?= new ItemCollection(@get('itemCollection'))
class ItemCollection extends Backbone.Collection
model: ItemModel
class ItemModel extends Backbone.Model
subCollection: ->
@_subCollection ?= new SubCollection(@get('subCollection'))
class SubCollection extends Backbone.Collection
model: SubModel
class SubModel extends Backbone.Model
mainModel = new MainModel(json)
然后,为了使mainModel.save()起作用,您需要在MainModel和ItemModel上覆盖toJSON,如:
class MainModel extends Backbone.Model
itemCollection: ->
@_itemCollection ?= new ItemCollection(@get('itemCollection'))
toJSON: ->
return _.extend(@attributes, {itemCollection: @itemCollection().toJSON()})
class ItemModel extends Backbone.Model
subCollection: ->
@_subCollection ?= new SubCollection(@get('subCollection'))
toJSON: ->
return _.extend(@attributes, {subCollection: @subCollection().toJSON()})
我在coffeescript中写了这个例子,因为它比javascript简洁得多。如果你需要任何帮助来理解它,请问问。
希望这有帮助!
---注意---
从技术上讲,在coffeescript中,toJSON方法可能只是:
toJSON: ->
_.extend @attributes, itemCollection: @itemCollection().toJSON()
但是我按照我的方式写了它,以便对非咖啡用户更容易理解。
答案 1 :(得分:1)
如果不查看整个代码库,我认为您的结构可能会略有错误。通常使用骨干我几乎不会将:el元素直接传递给视图。该视图负责生成它自己的el。在渲染之后,我将新的view.el插入到DOM中。如下所示
var subView = new FooView({ model: fooModel });
mainView.$(".list").append(subView.el);
在上面的例子中,每个子视图都有一个骨干对象。如果你需要 删除子视图,你不需要做一个选择器查询来找到它,你只需要调用 对象上的remove方法,它知道如何从dom中删除自己。
或者更具体地说,subView处理它自己的click事件 然后可以通过销毁它的相关模型然后调用自身的删除来处理