jQuery: 解除事件处理程序以便稍后重新绑定。

40

有人知道如何解除一组事件处理程序的绑定,但是记住它们以便以后重新绑定吗? 有什么建议吗?


你的事件有相同的处理程序函数吗?还是全部都不同? - bendewey
这不应该是问题。让我们假装它们都是不同的,我不知道它们是什么。 - glaz666
7个回答

23

数据项中有一个事件元素。这应该可以帮助你入门,你可以读取你的元素并将处理程序存储在数组中,然后解绑定。如果需要更多帮助,请评论。我从阅读$.fn.clone方法中得到了这个想法,所以也可以看一下。

$(document).ready(function() {
    $('#test').click(function(e) {
        alert('test');
        var events = $('#test').data("events");
        $('#test').unbind('click', events.click[0]);
    });
});

<a id="test">test</a>

1
我也在寻找解决这个问题的方法,而这个答案非常有效。为了更加通用,您可以通过迭代器访问events.click。 - Achimnol
3
在 jQuery 1.4.2 中,他们改变了事件存储方式,因此这种方法将不起作用:http://blog.jquery.com/2010/02/19/jquery-142-released/。我不确定你需要做什么替代方案。 - Xiong Chiamiov
1
处理1.4.2版本之后的绑定,请参见下面关于事件命名空间的文章。 - Michael Mikowski

8
自从jQuery 1.4.2版本之后,事件处理程序的存储方式发生了变化,因此以下内容非常相关:
我发现最好的方法是使用事件命名空间:
var ary_handlers = [ fn_highlight, fn_onpress, fn_cleanup ];
for ( idx = 0; idx < ary_handlers.length; idx++ ){
  $('#test').bind('click.foobar',ary_handlers[idx]);
}

// and then later: 
$('#test').unbind('.foobar');  

在上面的例子中,所有的foobar事件都被解绑了。请注意,如果您需要更精细的控制,您可以为每个点击处理程序命名空间,并将其与处理程序数组相关联:
var ary_handlers = [ fn_highlight, fn_onpress, fn_cleanup ];
for ( idx = 0; idx < ary_handlers.length; idx++ ){
  $('#test').bind('click.ns_' + String(idx), ary_handlers[idx]);
}

// and then later you could pick off a specific one to unbind
$('#test').unbind('.ns_2');

8

以下是如何实现此功能,提供了选择器上的storeEventsrestoreEvents方法。 storeEvents在调用时会对事件进行快照。 restoreEvents将恢复到最后一个先前的快照。可能需要在还原时稍微调整一下参数,以便对未绑定的内容进行参数化,也许您想保留最后一个快照后绑定的事件。

(function($){

    function obj_copy(obj){
            var out = {};
        for (i in obj) {
            if (typeof obj[i] == 'object') {
                out[i] = this.copy(obj[i]);
            }
            else
                out[i] = obj[i];
        }
        return out;
    }


    $.fn.extend({

        storeEvents:function(){
            this.each(function(){
                $.data(this,'storedEvents',obj_copy($(this).data('events')));
            });
            return this;
        },

        restoreEvents:function(){
            this.each(function(){
                var events = $.data(this,'storedEvents');
                if (events){
                    $(this).unbind();
                    for (var type in events){
                        for (var handler in events[type]){
                            $.event.add(
                                this, 
                                type, 
                                events[type][handler], 
                                events[type][handler].data);
                        }
                    }
                }
            });
            return this;
        }

    });
})(jQuery);

1
有一个名为Copy Events的jQuery插件,它可以将一个对象的事件复制到另一个对象。这可以非常容易地用于从一个元素中“保存”事件并稍后再次使用。只是多了一个选项 :)

编辑:修复了损坏的链接


0
为了解除事件处理程序,您需要将处理程序函数传递给unbind()。因此,您已经拥有处理程序函数,您只需要记住它即可。

我认为如果您不传递特定的处理程序函数,解绑将应用于该对象的所有事件? - Helmut
@Helmut 是的,如果你不带参数调用 unbind,它将解除所有处理程序。除非你保留了对它们的引用,否则你将无法在以后重新绑定它们。你也可能会解除你不知道的事件 - 例如由另一个脚本绑定的事件。最好使用特定的处理程序调用 unbind,这样你就可以确信。 - meouw

0
您可以使用event.handler参数:
$(document).ready(function() {
    $('#test').click(function(e) {
        e.preventDefault();
        alert('test');
        $('#test').unbind('click', e.handler);
        //Do Something...
        $('#test').click();
    });
});

<a id="test">test</a>

event.handler 返回接收事件的当前处理程序,因此通过省略它,您可以保留其他处理程序。


-3
Nick Craver似乎已经找到了适用于jQuery 1.4.2+的正确答案。他还提供了一个有用的fiddle。他的解决方案允许您检索附加到jQuery元素的所有事件处理程序,并找出它们所附加的处理程序。

6
投反对票的人应该提供他们为什么反对的理由。这有助于让被反对的人学习并且增加一点责任感...有时候反对者是错的。每个人都会学到东西。 - traday

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接