La vue Backbone.js ne peut pas dégager les événements correctement

J'ai un code Backbone.js qui lie un événement de clic à un bouton, et je veux le déconnecter après avoir cliqué, l'exemple de code ci-dessous:

var AppView = Backbone.View.extend({ el:$("#app-view"), initialize:function(){ _.bindAll(this,"cancel"); }, events:{ "click .button":"cancel" }, cancel:function(){ console.log("do something..."); this.$(".button").unbind("click"); } }); var view = new AppView(); 

Cependant, le unbind ne fonctionne pas, j'ai essayé de plusieurs façons différentes et fini un événement de liaison dans la fonction d'initialisation avec jQuery mais pas dans le modèle Backbone.events.

Quelqu'un sait pourquoi le unbind ne fonctionne pas?

La raison pour laquelle il ne fonctionne pas, c'est que Backbonejs ne lie pas l'événement sur le bouton DOM .button lui-même. Il délègue l'événement comme ceci:

 $(this.el).delegate('.button', 'click', yourCallback); 

(Docs: http://api.jquery.com/delegate )

Vous devez démêler l'événement comme ceci:

 $(this.el).undelegate('.button', 'click'); 

(Docs: http://api.jquery.com/undelegate )

Votre code devrait donc ressembler à:

 var AppView = Backbone.View.extend({ el:$("#app-view"), initialize:function(){ _.bindAll(this,"cancel"); }, events:{ "click .button":"cancel" }, cancel:function(){ console.log("do something..."); $(this.el).undelegate('.button', 'click'); } }); var view = new AppView(); 

Un autre moyen (peut-être mieux) de résoudre ceci est de créer un attribut d'état comme celui-ci. Il est this.isCancelable cancel chaque fois que la fonction d' cancel est appelée que vous vérifiez si this.isCancelable est défini sur true, si oui, vous poursuivez votre action et définissez this.isCancelable to false .

Un autre bouton pourrait réactiver le bouton d'annulation en définissant this.isCancelable sur true sans attacher / bloquer l'événement de clic.

Vous pourriez résoudre cette autre façon

 var AppView = Backbone.View.extend({ el:$("#app-view"), initialize:function(){ _.bindAll(this,"cancel"); }, events:{ "click .button":"do" }, do:_.once(function(){ console.log("do something..."); }) }); var view = new AppView(); 

Underscore.js une fois la fonction assure que la fonction enveloppée ne peut être appelée qu'une seule fois.

Il existe un moyen encore plus simple, en supposant que vous voulez démêler tous les événements:

 this.undelegateEvents(); 

J'aime la réponse à la bradgonesurfing. Cependant, j'ai rencontré un problème en utilisant l'approche _.once lorsque plusieurs instances de la vue sont créées. C'est-à-dire que _ une fois, restreindrait la fonction à appeler une seule fois pour tous les objets de ce type, c'est-à-dire que la restriction était au niveau de la classe plutôt qu'au niveau de l'instance.

J'ai abordé le problème de cette façon:

 App.Views.MyListItem = Backbone.View.extend({ events: { 'click a.delete' : 'onDelete' }, initialize: function() { _.bindAll(this); this.deleteMe = _.once(this.triggerDelete); }, // can only be called once triggerDelete: function() { console.log("triggerDelete"); // do stuff }, onDelete:(function (e) { e.preventDefault(); this.deleteMe(); }) }); 

J'espère que cela aidera quelqu'un

Vous pouvez simplement utiliser object.off , le code ci-dessous fonctionne pour moi

 initialize:function () { _.bindAll(this, 'render', 'mouseover', 'mouseout', 'delete', 'dropout' , 'unbind_mouseover', 'bind_mouseover'); ....... }, events: { 'mouseover': 'mouseover', 'unbind_mouseover': 'unbind_mouseover', 'bind_mouseover': 'bind_mouseover', ..... }, mouseover: function(){ $(this.el).addClass('hover'); this.$('.popout').show(); }, unbind_mouseover: function(){ console.log('unbind_mouseover'); $(this.el).off('mouseover'); }, bind_mouseover: function(){ ........ },