Backbone.js View не может отменить события должным образом
У меня есть код Backbone.js, который привязывает событие click к кнопке,
и я хочу отменить его после нажатия, пример кода, как показано ниже:
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();
Однако unbind не работает, я попробовал несколько разных способов и завершил привязку события к инициализации функции с помощью jQuery, но не в модели Backbone.events.
Кто-нибудь знает, почему unbind не работает?
Ответы
Ответ 1
Причина, по которой он не работает, заключается в том, что Backbonejs не связывает событие с самим элементом DOM Element. Он делегирует событие следующим образом:
$(this.el).delegate('.button', 'click', yourCallback);
(docs: http://api.jquery.com/delegate)
Вам нужно отключить событие следующим образом:
$(this.el).undelegate('.button', 'click');
(docs: http://api.jquery.com/undelegate)
Итак, ваш код должен выглядеть так:
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();
Другим (возможно, лучшим) способом решения этого является создание атрибута состояния, такого как this.isCancelable
, теперь каждый раз, когда вызывается функция cancel
, вы проверяете, установлено ли значение this.isCancelable
true, если да, вы выполните свое действие и установите this.isCancelable
в значение false.
Другая кнопка может повторно активировать кнопку отмены, установив this.isCancelable
в значение true без привязки/открепления события клика.
Ответ 2
Вы могли бы решить этот другой способ
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 однажды гарантирует, что завернутая функция
может быть вызван только один раз.
Ответ 3
Существует еще более простой способ, предполагая, что вы хотите отменить все события:
this.undelegateEvents();
Ответ 4
Мне нравится bradgonesurfing ответ. Однако я столкнулся с проблемой, использующей подход _.once, когда создаются несколько экземпляров представления. А именно, что _.once ограничил бы функцию, которая будет вызываться только один раз для всех объектов этого типа, то есть ограничение было на уровне класса, а не на уровне экземпляра.
Я обработал проблему следующим образом:
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();
})
});
Надеюсь, это поможет кому-то
Ответ 5
вы можете просто использовать object.off, код ниже работает для меня
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(){
........
},