我有一个负责渲染 * 子视图 * 的 * 超级视图 。当我 * 重新渲染**超级视图 * 时, 子视图 * 中的所有事件都将丢失。
这是一个例子:
var SubView = Backbone.View.extend({
events: {
"click": "click"
},
click: function(){
console.log( "click!" );
},
render: function(){
this.$el.html( "click me" );
return this;
}
});
var Composer = Backbone.View.extend({
initialize: function(){
this.subView = new SubView();
},
render: function(){
this.$el.html( this.subView.render().el );
}
});
var composer = new Composer({el: $('#composer')});
composer.render();
当我点击 click me div时,事件被触发。如果我再次执行composer.render()
,一切看起来都很相似,但是 *click事件 * 不再被触发。
检查working jsFiddle。
3条答案
按热度按时间wz3gfoph1#
执行此操作时:
你实际上是在说:
并且
empty
终止this.$el
内所有对象上的事件:为了避免内存泄漏,jQuery在删除元素本身之前,会从子元素中删除其他结构,如数据和事件处理程序。
因此,您丢失了绑定
this.subView
上的事件的delegate
调用,并且SubView#render
不会重新绑定它们。你需要将一个
this.subView.delegateEvents()
调用转移到this.$el.html()
中,但是你需要它发生在empty()
之后。你可以这样做:演示:http://jsfiddle.net/ambiguous/57maA/1/
还是这样:
演示:http://jsfiddle.net/ambiguous/4qrRa/
或者,您可以在渲染时使用
remove
并重新创建this.subView
,这样就可以避开问题(但这可能会导致其他问题...)。33qvvth12#
这里有一个更简单的解决方案,它一开始就不会把活动注册吹走:
jQuery.detach()
.http://jsfiddle.net/ypG8U/1/
但出于性能原因,这种变化可能更可取:
http://jsfiddle.net/ypG8U/2/
很明显,这是一个简化的例子,其中子视图是父视图的唯一内容。如果是这样的话,你可以重新呈现子视图。如果有其他内容,你可以这样做:
或
此外,在原始代码中,以及在@mu的回答中重复的是,一个DOM对象被传递给
jQuery.html()
,但该方法只被记录为接受HTML字符串:jQuery.html()
的记录签名:http://api.jquery.com/html/#html2
huwehgph3#
当使用
$(el).empty()
时,它会删除选定元素中的所有子元素**,并删除所有绑定到选定元素(el
)内任何(子)元素的事件**(和数据)。若要保留系结至*子项目**的事件,但仍要移除子项目,请用途:
$(el).children().detach();
而不是$(.el).empty();
这将允许您的视图成功地重新呈现,并且事件仍在绑定和工作。