使用bind时,jQuery off()不会解除绑定事件

时间:2015-03-02 00:07:00

标签: javascript jquery bind jquery-events

function bubble(content, triggerElm){
  this.element = $('<div class="bubble" />').html(content);
  this.element.css(.....) // here is positioned based on triggerElm
}

bubble.prototype.show = function(){
  $(document).on('click', this._click.bind(this));
  this.element.css(....)
};

bubble.prototype.hide = function(){
  $(document).off('click', this._click.bind(this));
  this.element.css(....)
};  

bubble.prototype._click = function(event){
  console.log('click', this);

  if(this.element.is(event.target) || (this.element.has(event.target).length > 0))
    return true;

  this.hide();
};

var b = new bubble();
b.show();
b.hide();

我一直看到在控制台中点击,因此点击不会解除绑定。 但是,如果我删除了bind()来电,那么点击就会解除绑定。有谁知道为什么?我需要一种能够在我的测试函数中更改“this”的方法,这就是我使用bind()的原因。

5 个答案:

答案 0 :(得分:5)

一个选项是namespace the event

$(document).on('click.name', test.bind(this));
$(document).off('click.name');

Example Here

答案 1 :(得分:5)

问题在于this._click.bind()每次调用时都会创建一个新函数。为了分离特定的事件处理程序,您需要传入用于创建事件处理程序的原始函数,并且这里没有发生,因此不会删除处理程序。

如果您的应用中只有一些bubble,那么您可以选择道格拉斯克罗克福德的路线而不是this。这将消除很多关于this所指的内容的混淆,并确保每个bubble保留对其自己的click函数的引用,该函数可用于根据需要删除事件:

function bubble(content, tiggerElm) {
    var element = $('<div class="bubble" />').html(content);
    element.css(.....); // here is positioned based on triggerElm

    function click(event) {
        console.log('click', element);
        if (element.is(event.target) || 
            element.has(event.target).length > 0) {
            return true;
        }
        hide();
    }

    function show() {
        $(document).on('click', click);
        element.css(....);
    }

    function hide() {
        $(document).off('click', click);
        element.css(....);
    } 

    return {
        show: show,
        hide: hide
    };
}

var b1 = bubble(..., ...);
b1.show();

var b2 = bubble(..., ...);
b2.show();

了解这是如何使您免于使用.bind()和下划线前缀方法等设计。

答案 2 :(得分:4)

尝试使用jQuery的代理来获取您的函数的唯一引用。

这样,当你调用$ .proxy(test,this)时,它会检查之前是否已经引用过这个函数。如果是,代理将返回该引用,否则它将创建一个并将其返回给您。这样,您可以始终获得原始函数,而不是一遍又一遍地创建它(比如使用bind)。

因此,当你调用off()并传递测试函数的引用时,off()将从click事件中删除你的函数。

此外,您的测试功能应在使用前声明。

var test = function(){
      console.log('click');
};    

$(document).on('click', $.proxy(test, this));
$(document).off('click', $.proxy(test, this));

http://jsfiddle.net/aw50yj7f/

答案 3 :(得分:3)

请阅读https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

bind创建一个新函数,因此执行$(document).on('click', test.bind(this));就像$(document).on('click', function(){});一样,每次执行它时都会调用一个新的匿名函数,因此你没有对unbind的引用。

如果你会这样做:

var test = function(){
     console.log('click');
};

var newFunct = test.bind(this);
$(document).on('click', newFunct );
$(document).off('click', newFunct );

它应该可以正常工作

例如:http://jsfiddle.net/508dr0hv/

另外 - 建议不要使用bind,它很慢并且在某些浏览器中不受支持。

答案 4 :(得分:0)

而不是将此绑定到事件,而是将其作为参数发送:

$("#DOM").on("click",{
'_this':this
},myFun);

myFun(e){
 console.info(e.data._this);
$("#DOM").off("click",myFun);
}