javascript Backbone.js View 无法正确解绑事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6831362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Backbone.js View can't unbind events properly
提问by Jimchao
I have some Backbone.js code that bind a click event to a button, and I want to unbind it after clicked, the code sample as below:
我有一些将点击事件绑定到按钮的 Backbone.js 代码,我想在点击后取消绑定,代码示例如下:
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();
However the unbind is not working, I tried several different way and end up binding event in initialize function with jQuery but not in Backbone.events model.
然而,解除绑定不起作用,我尝试了几种不同的方式,最终在使用 jQuery 的初始化函数中绑定事件,但在 Backbone.events 模型中没有。
Anyone know why the unbind is not working?
任何人都知道为什么 unbind 不起作用?
回答by sled
The reason it doesn't work is that Backbonejs doesn't bind the event on the DOM Element .button itself. It delegates the event like this:
它不起作用的原因是 Backbonejs 没有在 DOM Element .button 本身上绑定事件。它像这样委托事件:
$(this.el).delegate('.button', 'click', yourCallback);
(docs: http://api.jquery.com/delegate)
(文档:http: //api.jquery.com/delegate)
You have to undelegate the event like this:
您必须像这样取消委托事件:
$(this.el).undelegate('.button', 'click');
(docs: http://api.jquery.com/undelegate)
(文档:http: //api.jquery.com/undelegate)
So your code should look like:
所以你的代码应该是这样的:
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();
Another (maybe better) way to solve this is to create a state attribute like this.isCancelable
now everytime the cancel
function is called you check if this.isCancelable
is set to true, if yes you proceed your action and set this.isCancelable
to false.
解决此问题的另一种(可能更好)方法是创建一个状态属性,就像this.isCancelable
现在每次cancel
调用函数时检查是否this.isCancelable
设置为 true,如果是,则继续操作并设置this.isCancelable
为 false。
Another button could reactivate the cancel button by setting this.isCancelable
to true without binding/unbinding the click event.
另一个按钮可以通过设置this.isCancelable
为 true重新激活取消按钮,而不绑定/取消绑定点击事件。
回答by bradgonesurfing
You could solve this another way
你可以用另一种方式解决这个问题
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 once function ensures that the wrapped function can only be called once.
underscore.js once 函数确保被包装的函数只能被调用一次。
回答by Garrett
There is an even easier way, assuming you want to undelegate allevents:
假设您想取消所有事件的委托,还有一种更简单的方法:
this.undelegateEvents();
回答by b73
I like bradgonesurfing answer. However I came across a problem using the _.once approach when multiple instances of the View are created. Namely that _.once would restrict the function to be called only once for all objects of that type i.e. the restriction was at the class level rather than instance level.
我喜欢 bradgonesurfing 的回答。但是,当创建多个视图实例时,我在使用 _.once 方法时遇到了问题。即 _.once 将限制该函数只能为该类型的所有对象调用一次,即限制是在类级别而不是实例级别。
I handled the problem this way:
我是这样处理问题的:
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();
})
});
Hopefully this will help someone
希望这会帮助某人
回答by delai
you can simply use object.off, the code below is work for me
你可以简单地使用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(){
........
},