レンダリングを担当するsuper-Viewがいるsub-Views 。 re-rendersuper-Viewのすべてのイベントをサブビューは失われます。
これは例です:
_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 medivをクリックすると、イベントがトリガーされます。 composer.render()
をもう一度実行すると、すべてが同じように見えますが、クリックイベントがトリガーされなくなりました。
working 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
をレンダリングして_this.subView
_を再作成し、その方法で問題を回避できます(ただし、他の問題が発生する可能性があります...)。
最初の場所でイベント登録を吹き飛ばさない簡単な解決策があります:jQuery.detach()
。
_this.subView.render().$el.detach().appendTo( this.$el );
_
ただし、パフォーマンス上の理由から、このバリエーションはおそらく望ましいものです。
_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()
に渡されますが、そのメソッドはHTMLの文字列を受け入れるものとしてのみ文書化されています。
_this.$el.html( this.subView.render().el );
_
文書化されたjQuery.html()
の署名:
_.html( htmlString )
_
$(el).empty()
を使用すると、選択した要素のすべての子要素が削除されますANDはALLを削除しますイベント(およびデータ)にバインドされています任意の(子)要素選択した要素の内部(el
)。
イベントのバインドを維持する子要素でも、子要素を削除するには、次を使用します。
$(el).children().detach();
の代わりに$(.el).empty();
これにより、ビューがまだバインドされて機能している状態でビューを正常に再レンダリングできます。