主要成分:事件中失去了重新渲染(Backbone: event lost in re-render)

2019-06-17 18:42发布

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

这是一个例子:

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 。

Answer 1:

当你这样做:

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

你实际上是说这样的:

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

empty杀死里面的一切事件, this.$el

以避免内存泄漏,jQuery的去除元件本身之前除去其他结构,例如从子元素数据和事件处理程序。

所以,你失去了delegate电话结合的事件this.subViewSubView#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并重新创建this.subView渲染时和回避问题的方式(但这也可能导致其他问题...)。



Answer 2:

这里有一个简单的解决方案,不摆在首位吹走事件注册: jQuery.detach()

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

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

这种变化可能是由于性能原因最好不过:

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

} );

// ...

此外,在你的原代码,并在@亩的回答重复,一个DOM对象传递给jQuery.html()但该方法是只记录为接受HTML的字符串:

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

记录签名jQuery.html()

.html( htmlString )

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



Answer 3:

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

为了保持绑定到 子元素 的事件 ,但还是删除子元素,使用方法:

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

这将使你的观点与仍然结合和工作的事件成功地重新呈现。



文章来源: Backbone: event lost in re-render