骨干:在重新渲染中丢失的事件

我有超级查看谁负责渲染子视图 。 当我重新渲染 超级查看 视图中的所有事件都丢失了。

这是一个例子:

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(); 

当我点击 div时触发事件。 如果我再次执行composer.render() ,所有东西都看起来很相似,但是click事件不再被触发。

检查工作jsFiddle 。

当你这样做:

 this.$el.html( this.subView.render().el ); 

你有效地这样说:

 this.$el.empty(); this.$el.append( this.subView.render().el ); 

empty杀死在这里的一切事件this.$el

为了避免内存泄漏,jQuery在删除元素本身之前从子元素中删除其他构造,如数据和事件处理程序。

所以你失去了绑定this.subView事件的delegate调用和SubView#render不会重新绑定它们。

你需要将this.subView.delegateEvents()调用放到this.$el.html()但是你需要在empty()后面发生。 你可以这样做:

 render: function(){ console.log( "Composer.render" ); this.$el.empty(); this.subView.delegateEvents(); this.$el.append( this.subView.render().el ); return this; } 

演示: http : //jsfiddle.net/ambiguous/57maA/1/

或者像这样:

 render: function(){ console.log( "Composer.render" ); this.$el.html( this.subView.render().el ); this.subView.delegateEvents(); return this; } 

演示: http : //jsfiddle.net/ambiguous/4qrRa/

或者你可以remove并重新创buildthis.subView时,这样渲染和回避问题(但这可能会导致其他问题…)。

这里有一个更简单的解决scheme,它不会把事件注册放在第一位: jQuery.detach()

http://jsfiddle.net/ypG8U/1/

 this.subView.render().$el.detach().appendTo( this.$el ); 

尽pipe这种变化可能是出于性能的原因:

http://jsfiddle.net/ypG8U/2/

 this.subView.$el.detach(); this.subView.render().$el.appendTo( this.$el ); // or this.$el.append( this.subView.render().el ); 

显然,这是一个简单的匹配例子,其中子视图是父级的唯一内容。 如果真的如此,你可以重新渲染子视图。 如果有其他内容,你可以做一些事情:

 var children = array[]; this.$el.children().detach(); children.push( subView.render().el ); // ... this.$el.append( children ); 

要么

 _( this.subViews ).each( function ( subView ) { subView.$el.detach(); } ); // ... 

另外,在您的原始代码中,并在@ mu的答案中重复,DOM对象被传递给jQuery.html() ,但该方法仅被logging为接受HTML的string:

 this.$el.html( this.subView.render().el ); 

loggingjQuery.html()签名:

 .html( htmlString ) 

http://api.jquery.com/html/#html2

当使用$(el).empty()它将删除所选元素中的所有子元素,并删除与所选元素( el )内的任何(子元素)元素绑定的 所有 事件 (和数据)。

为了使事件绑定到 子元素 ,但仍然删除子元素,请使用:

$(el).children().detach(); 而不是$(.el).empty();

这将允许您的视图顺利重新绑定事件仍然绑定和工作。