Backbone.js View无法正确取消绑定事件

时间:2011-07-26 14:11:59

标签: javascript jquery backbone.js

我有一些将click事件绑定到按钮的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();

然而unbind无法正常工作,我尝试了几种不同的方式,并在jQuery初始化函数中结束事件,但在Backbone.events模型中没有。

任何人都知道为什么unbind不起作用?

5 个答案:

答案 0 :(得分:37)

它不起作用的原因是Backbonejs没有绑定DOM Element .button本身的事件。它委托这样的事件:

$(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来重新激活取消按钮,而不绑定/取消绑定点击事件。

答案 1 :(得分:17)

你可以用另一种方式解决

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一旦函数确保包装函数 只能被召唤一次。

答案 2 :(得分:7)

假设您想要取消所有事件,有一种更简单的方法:

this.undelegateEvents();

答案 3 :(得分:2)

我喜欢bradgonesurfing的答案。但是,当创建View的多个实例时,我遇到了使用_.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();
  })
});

希望这会帮助某人

答案 4 :(得分:1)

您只需使用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(){
    ........
},