Posted at

Viewに登録したイベントが複数回呼ばれてしまう場合の対処

More than 5 years have passed since last update.

以下のように、同じDOM要素に対して複数のBackboneのViewを適用すると、それぞれのイベントが残り続けてしまい、セレクタがかぶると二重にイベントが発生してしまいます。Viewがひとつの場合でも、Routerを使って同じViewを複数回表示した場合も同様です。

var AView = Backbone.View.extend({

el: $("#main"),
events: {
"click button#btn1": "onBtn1Click"
}
...
});
var BView = Backbone.View.extend({
el: $("#main"),
events: {
"click button#btn1": "onBtn1Click"
}
...
});

Backbone.Viewが持つremove()が使えるかと思ったのですが、DOM要素は消えてもイベント自体は残り続けていました。

この現象を解決するためには、Backbone.Viewが持つundelegateEvents()を呼び出す必要があります。別のViewに移動したタイミングで、

this.off();

this.undelegateEvents();
this.remove();

といった形でViewを破棄すると良いかと思います。

Backboneの実装を見たら

// Clears all callbacks previously bound to the view with `delegateEvents`.

// You usually don't need to use this, but may wish to if you have multiple
// Backbone views attached to the same DOM element.
undelegateEvents: function() {
this.$el.off('.delegateEvents' + this.cid);
return this;
},

と最初から書いてあった。困ったら実装見なきゃダメですね(^^;