如何从特定名称空间解除所有jQuery事件的绑定?

如何从特定名称空间解除所有jQuery事件的绑定?,jquery,events,Jquery,Events,jQuery中是否有一个“全局”取消绑定函数,以便我能够从给定的命名空间中删除所有绑定事件?例如: // assume these are the events bound to different elements $('#foo').bind('click.myNS', ...); $('#bar').bind('keyup.myNS', ...); $('#baz').bind('dblclick.myNS', ...); // magic occurs here... $.ma

jQuery中是否有一个“全局”取消绑定函数,以便我能够从给定的命名空间中删除所有绑定事件?例如:

// assume these are the events bound to different elements
$('#foo').bind('click.myNS', ...);
$('#bar').bind('keyup.myNS', ...);
$('#baz').bind('dblclick.myNS', ...);    

// magic occurs here...
$.magicalGlobalUnbindFunction('.myNS');

// ...and afterwards, the three binds from above are gone

我看到的所有unbind示例都要求首先选择一些元素。我想从技术上讲,你可以做
$('*').unbind('.myNS')
,但这似乎效率很低。

你可以将
myNS
作为一个类添加到你想要解除事件绑定的每个元素中。

你确实在寻找一个神奇的全局函数,但像往常一样,在这种情况下,你只能得到幻觉,简单

还有使用or的jQuery解决方案(or是live()的唯一变体)

使用
$(“body”).delegate(“#foo”,“click.myNs”,func)
还可以绑定事件,使用
$(“body”).undelegate(.myNs”)
可以解除绑定。我在这里使用“body”元素,但当然,您可以使用作为所有需要绑定的元素的祖先的任何元素


它将使“解除绑定”工作更快,但也会使事件响应更慢。

您应该在绑定函数中添加一个类

$('#foo').bind('click.myNS', ...).addClass('removeLater');
$('#bar').bind('keyup.myNS', ...).addClass('removeLater');
$('#baz').bind('dblclick.myNS', ...).addClass('removeLater');  
然后呢

$('.removeLater').unbind();
如果
#foo
#bar
#etc
都是相同的元素或一小部分,您还可以执行以下操作:

$('div, button').unbind();

但是,如果您有一个不想删除的绑定事件,那么这不是一个好主意

您需要侵入jQuery内部,下面是一个简单实现的工作演示:


主要的工作是在常规的js循环中完成的,并且不会非常低效,因为即使这个页面最终也只包含106个要循环的项目。当然,您应该尽可能多地使用事件委派,以使jQuery处理程序集合中的项目数量尽可能少。

您可以始终包装$.fn.bind,然后缓存必要的引用:

(function ($) {
    var origBind = $.fn.bind,
        boundHash = {};

    $.fn.bind = function (type, data, fn) {
        var namespace = '',
            events = [];

        if (typeof type === 'string') {
            // @todo check the allowed chars for event namespaces.
            namespace = type.replace(/^[^.]+/, '');

            if (namespace.length) {
                events = boundHash[namespace];

                // Namespaces can hold any number of events.
                events = boundHash[namespace] = $.isArray(events) ? events : [];

                // Only really need ref to the html element(s)    
                events.push({
                    type: type, 
                    fn: $.isFunction(fn) ? fn : data, 
                    that: this.length > 1 ? this.toArray() : this[0]
                });
            }
        }

        origBind.apply(this, arguments);
    };

    // namespace to be muffled. Feel free to qualify a specific event type.
    $.muffle = function (namespace, type) {
        var events = [];

        if (boundHash.hasOwnProperty(namespace)) {
            events = boundHash[namespace];

            $.map(events, function (event) {
                var _type = type || event.type;

                if (event.type.indexOf(_type) === 0) {
                    $(event.that).unbind(_type, event.fn);
                }
            });

            // @todo think of better return value.
            return true;
        }

        // @todo think of better return value.
        return false
    };
})(jQuery);

您可以重写jquery的bind方法,然后在重写中存储关联数组中所有命名空间和相应事件的引用,然后根据要解除绑定的命名空间事件访问数组。代码可能是这样的

var eventArray=[];
(function ($) {
    var bind = $.fn.bind;
    $.fn.bind= function () {
    var result = bind.apply(this, arguments);
    var selector=arguments[0];
    var nameSpace= selector.split(".")[1];   //code to select the nameSpace eg. click.myNS o/p->myNS (update this if your selector has multiple '.')
    if(!eventArray[nameSpace])    //if the associative array does not contain the namespace yet
    {
       eventArray[nameSpace]=[];
    }
    eventArray[nameSpace].push(selector);
    return result;
};
})(jQuery);
现在使用eventArray,您可以随心所欲地解除绑定。用于解除命名空间myNS上所有事件绑定的代码如下所示:

$.each(eventArray['myNS'],function(){
   $(this).unbind();
});
希望这是一个好的解决方案。如果我有任何错误,请告诉我。

您需要使用jQuery的和方法。使用文档作为选择器

$(document).off('.myNS');

$(document).on('click.myNS','#foo', ...);
$(document).on('keyup.myNS','#bar', ...);
$(document).on('dblclick.myNS','#baz',''');
然后你的方法看起来像

$(document).on('click.myNS','#foo', fooClicked);
var fooClicked = function(e){
    var $this = $(e.target);
    // do stuff
}

我认为HTML没有名称间隔,这是事件绑定到的地方。@jondavidjohn:这种名称间隔形式是由jQuery提供的:它只是一种组织事件处理程序的方法,可以轻松地解除绑定,而不会影响其他任何人的(如插件)。@jondavidjohn:no,但是使用jquery,您可以为事件提供自己的名称空间。因此,这里的问题是“有没有[jquery]方法可以选择x名称空间的所有绑定事件”@jondavidjohn:请参阅此处,以了解jquery团队应该处理此类功能的更多信息。那太好了。这就是他所说的似乎“非常低效”@user120242:no,OP说使用*作为选择器将是低效的,因为它基本上会从页面上的每个元素中查找并尝试解除事件的绑定。mikerobi的建议是,在绑定时,向元素添加一个特定的类名,然后稍后使用该类名作为选择器,这样您就只能选择相关的元素。依我看,这可能是最好的解决方案……假设jquery没有内置其他东西……它可能。。。在内部,它保留了一个带有名称空间的列表……即使没有官方的选择器说“使用此事件名称空间选择所有元素”,理论上创建一个jquery插件来实现这一点应该足够容易。+1有时候,一个不太“工程化”的解决方案是最好的,我认为这里就是这样。这完全满足了要求,没有增加bug的风险。是的,处理程序的名称空间不幸地存储在缓存对象中很深,这就是为什么有这么多内部循环和tmp变量:(但如果你把它藏起来,只使用公共方法,你永远不会知道它有多脏是的,我也考虑过你的技术。我想我们解决方案之间的真正区别是我的需要更多的空间,你的需要更多的处理能力。我没有注意到还有另一个清晰的答案(你的).我认为你的更好,因为我的想法是“在盒子里”还有一个快速的暴力破解:P尽管我仍然会使用jQuery内部来移除事件,因为它们采用常规DOM元素,并且不需要浪费创建新jQuery对象的效率。这个解决方案肯定符合我的预期。但是考虑到你必须深入jQuery,我认为它将非常脆弱n jQuery的未来版本。+1的小提琴虽然。谢谢!我删除了回购协议,所以删除了相关的评论。做得好!这是超级简洁,并正确使用了名称空间。