模型主干视图在第一次集合重新渲染时无法从 DOM 中删除
Posted
技术标签:
【中文标题】模型主干视图在第一次集合重新渲染时无法从 DOM 中删除【英文标题】:Model Backbone Views can't be removed from DOM at first Collection re-render 【发布时间】:2013-05-04 11:07:57 【问题描述】:我一整天都在面对一个问题,我有点绝望!我很确定这对于这里的一些 Backbone 专家来说会很简单......我是 Backbone 的新手,我可能没有采取最好的方法。任何帮助或建议都会很棒!
问题
将新项目添加到集合后,该集合被重新渲染,我可以看到新项目添加到我的 DOM 中。 如果我单击“删除”按钮,则事件被触发,新项目被销毁......但元素保留在 DOM 中。如果我重新渲染页面,(刷新或导航到其他地方并返回)它就消失了。
而如果我添加一个新项目,在我的集合被渲染后立即导航到其他地方,然后返回并按“删除”,这一次它会被销毁并从 DOM 中删除...... 有什么想法吗?
添加新项目
save: function(e)
e.preventDefault();
var data = form2js('deviceForm', '.', true);
//Allow to create or edit a model;
this.model.set(data);
this.model = this.collection.create(this.model,
wait: true,
success: function()
Utils.alert('success', 'Device has been added/edited');
app.vent.trigger("devices:show");
);
此代码在我添加新项目时显示的视图内。添加新项目时,它会调用下面的函数。 this.collection 是我的设备列表,在路由器内部重复使用。
路由器
showDevices: function()
if (!this.devices)
this.devices = new Devices();
this.devices.fetch();
if (this.devicesList) this.devicesList.remove();
this.devicesList = new DevicesView(collection: this.devices);
$('.addPadding').hide().slideDown(1000, 'linear').html(this.devicesList.render().el);
,
我只提取一次列表,然后在每次需要时重复使用它,避免不必要的提取。如果存在,我会清理视图并实例化一个新视图。
收藏(查看)
initialize: function()
_.bindAll(this, "render", "addOne");
this.collection.on('add', this.addOne);
this.collection.on('reset', this.addAll);
,
render: function()
this.$el.html(this.template);
this.addAll();
return this;
,
addOne:function(device)
var devi = new DeviceView(model: device);
this.$el.find(".devices-list").append(devi.render().el);
,
addAll: function()
this.collection.each(this.addOne, this)
我的集合视图中没有定义 el 属性。绑定到集合事件,以便为新项目呈现或获取完成。
项目视图
tagName: 'tr',
events:
'click .remDevice': 'removeDevice',
'click .editDevice' : 'editDevice'
,
template: _.template( template ),
initialize: function()
this.listenTo(this.model, 'destroy', this.remove);
,
render: function()
this.$el.html(this.template(this.model.toJSON()));
return this;
,
removeDevice:function()
this.model.destroy();
我的项目被附加到表格中,添加到 tbody 元素中。该表位于我的集合视图的模板中。当我单击删除按钮时,模型被销毁并触发事件并调用 this.remove。但是在创建项目后重新呈现集合时不起作用。虽然之后工作......
希望我提供了足够的信息!提前非常感谢! PS:控制台没有错误,我的调试器中填充了模型+集合。
编辑: this.remove 在每次点击时都会被调用,因为我的模型每次都会被破坏。通过覆盖它并尝试手动删除元素:
this.$el.remove();
没有区别,也没有显示任何错误。 this.$el 包含我新添加的元素。
编辑 2 一条新线索:如果我有 6 个设备的集合,添加第 7 个,然后尝试删除其中任何一个,除非我重新渲染,否则它们会被销毁但不会从 DOM 中删除。所以它不仅仅与新项目相关联,而是我向集合中添加了一个新项目,渲染它并尝试删除一个项目。 此外,编辑功能仍然适用于每个项目,并将我重定向到具有正确模型的正确页面进行编辑。
LAST EDIT 我之前尝试清空集合以添加新项目以避免僵尸......但没有改变任何东西。我希望它能避免随机的副作用 在我的收藏视图中
addAll: function()
this.$el.find(".devices-list").empty();
this.collection.each(this.addOne, this)
,
【问题讨论】:
我还不完全确定为什么,但我不喜欢您收藏视图中的行_.bindAll(this, "render", "addOne");
那行在做什么?如果你删除它,它会起作用吗?
从您在 Collection 下提供的代码看来,它实际上是一个视图。
@MikeV,那一行相当于做 _this = this,然后在我的其他函数中使用 _this。它只是让我的上下文保持我的观点。感谢您的编辑!对此感到抱歉
如果您将第三个 this
参数添加到您的 collection.on()
行,您将不需要 _.bindAll
的东西。我尽量避免使用_.bindAll
调试您的 ItemView/DeviceView 的一个好方法是添加 this.model.on('all', function(eventName)console.log(eventName));
然后检查控制台以查看正在触发的事件。你真的只需要弄清楚为什么destroy
事件没有触发remove
函数。一旦你解决了这个问题,我想你会解决你的问题。我删除了我的答案,因为它不是解决方案。
【参考方案1】:
我找到了一种“肮脏”的方法来解决我的问题。 我在“删除函数”中有一个断点。直观地比较 this.$el 和添加到表中的行是完全相同的行。
所以我尝试这样做:
$('.devices-list').find(this.$el)
但没有返回任何内容...这太疯狂了,因为它们包含完全相同的数据!我假设 this.$el 以僵尸版本或其他形式呈现。我很确定这些项目的渲染方式有问题……但我肯定找不到,我愿意接受建议……
解决方案
在我的设备视图/项目视图中,我编辑了这两个函数,将模型id添加到tr,然后使用jquery在DOM中找到它。像这样,我专注于现有元素,而不是缓存 jquery 东西的 $el...
render: function()
this.$el.html(this.template(this.model.toJSON()));
this.$el.attr('id', this.model.id);
return this;
,
remove: function()
var elem = $('.devices-list').find('#'+this.model.id);
$(elem).find('#'+this.model.id).slideUp(1000);
$(elem).find('#'+this.model.id).remove();
希望有人会得到一个更好的主意,或者有人会从我的解决方案中得到帮助!
【讨论】:
以上是关于模型主干视图在第一次集合重新渲染时无法从 DOM 中删除的主要内容,如果未能解决你的问题,请参考以下文章