如何从特定名称空间解除所有jQuery事件的绑定?
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
// 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的小提琴虽然。谢谢!我删除了回购协议,所以删除了相关的评论。做得好!这是超级简洁,并正确使用了名称空间。