在 jQuery 中添加事件监听器非常简单。删除事件监听器也同样简单。您可能希望删除监听器,因为您不再关心对该事件执行任何操作,或者是为了减少内存使用,或者两者兼而有之。但是,假设您已将多个监听器附加到同一事件。如何只删除其中一个?命名空间可以提供帮助。
让我们看看代码。
$("#element")
.on("click", doSomething)
.on("click", doSomethingElse);
当我们选择的元素被点击时,两者 doSomething
和 doSomethingElse
都会触发。这很好。这是使用 jQuery 绑定事件而不是超级老式的 onclick
的一个优势,后者会覆盖之前声明的事件处理程序。
现在假设您想删除第一个事件监听器,即触发 doSomething
的那个。您该怎么做呢?
$("#element").off("click");
小心,这会解除这两个处理程序的绑定,而这并非我们想要的结果。
幸运的是,jQuery 会在 .off()
中使用与 .on()
相同的第二个参数。
$("#element").off("click", doSomething);
如果您有实际函数的引用,可以将其作为参数传递,这很好。但是,如果您没有该引用怎么办?可能是因为您不知道它是什么,或者您使用了匿名函数作为处理程序,如下所示
$("#element")
.on("click", function() {
console.log("doSomething");
});
如何以安全的方式解除该事件的绑定,而不会意外地解除其他 click 处理程序的绑定?命名空间事件!
不要只使用 click
作为事件名称,您可以使用 click.namespace
。
$("#element")
.on("click.myNamespace", function() {
console.log("doSomething");
});
现在,您可以使用带有该确切事件名称的 .off()
来解除仅它的绑定。
$("#element").off("click.myNamespace");
jQuery 中一些很酷的有用功能之一。即使使用 addEventListener
和 removeEventListener
进行现代事件绑定,这也会有点棘手(我认为)。
我最近在我的 用于测试行长的书签 中使用了它。我基本上想在页面上的每个元素上绑定 mouseenter
事件(使用委托),然后当其中一个被点击时,解除这两个事件的绑定。但我希望小心不要解除我没有自己绑定的任何事件。因此,使用了命名空间!
这在 Zepto 中也有效,并且在编写单元测试并需要清理对象以进行后续测试时非常有用。
嘘,我知道命名空间,但老实说,我不认为它们在 jQuery 中是原生实现的。我以为您必须手动添加事件监听器才能在插件中使用命名空间事件。
感谢您的提示!
命名空间的另一个很酷的功能是您可以拥有多个级别的命名空间。例如,您可以执行以下操作
$('.some-div').on('click.myPlugin.submitButtonClick', '.submit-button', handlerFunction)
因此,您可以为命名空间中的所有事件或其中一个事件调用 .off()。
本文还应提及有关取消命名空间中的所有事件,这对 jQuery 插件非常有用。
+1
令人惊讶的是,这些小信息在网上如此难以找到。虽然一个小小的 jsfiddle 奏效了,所以我在寻找一个地方来验证我的直觉是否正确,即仅将命名空间传递给解除事件绑定。
谢谢
我一直在考虑命名空间,并想知道是否有办法将地理位置注入到命名空间中,以便 RSS 提要转换为 GeoRSS。这是否可以通过 jQuery 实现?
您可以使用
$("#element").on("click",function(){})
吗?我以为唯一的方法是$("element").onclick(function(){});
。前者有什么优势?我认为
onclick()
不是 jQuery 中的函数,但click()
是。我认为区别在于on()
会绑定到元素,无论它们是否存在于 DOM 中,或者是否在以后的某个时间点动态添加。不是“onclick”,而是“click”,它是
on("click", function)
的快捷方式。使用on
,您可以附加多个事件 -$(el).on("click focus", function (){});
,您还可以创建单个事件,如果e.target
位于事件冒泡中,则该事件将触发,从而提高性能。$("table").on("click", "td", function () {});
– 单个事件$("table td").click(function () {});
– 事件数量 == $(‘table td’).length如前所述,Zepto 也支持此功能,但我注意到您对原生事件(如
click.MyNamespace
或focus.MyNamespace
)使用 .MyNamespace,而对自定义事件使用反向语法:MyNamespace:eventName
。jQuery 似乎足够智能,可以以任何方式理解它,但如果您希望它在 Zepto 和 jQuery 中都能工作,则必须对自定义事件使用不同的语法。
我在 Intimidatetime 中经历了这场战斗。因此,对于标准原生事件,它使用
click.intimidatetime
,但对于自定义事件,我必须使用intimidatetime:open
或intimidatetime:change
非常感谢这篇文章。这将解决我过去在某些函数中遇到的某些问题。
嘿,Chris,你能为 Digitally Imported 中显示的导航栏动画发布一个片段教程吗?
http://www.di.fm
点击频道。
我相信它是 jQuery UI,但不确定。
啊,太棒了,我将尽快尝试一下。
谢谢!
:D
这两种用途是如果我们不知道相关函数的名称或使用了匿名函数。但是,实现命名空间的唯一方法似乎是在声明函数时,您可以在其中传递一个您知道的名称的函数。它似乎只是传递已命名函数的另一种方法?我是否错过了此功能的其他用途?
如果您使用代理 (
$.proxy
),并且以后需要分离它们,则需要跟踪您创建的每个代理,或者只使用命名空间。这太棒了。
一件非常好的事情,但我遇到了麻烦,那就是**动态命名空间**……以下是我更喜欢绑定事件的方式(以
json
格式)在这种情况下,我无法使命名空间动态化,但在接下来的场景中,我可以创建一个动态命名空间
动态命名空间对于插件等非常有用,在这些插件中,您希望在一个页面上创建 > 1 个插件实例,但在销毁插件时不解除所有其他绑定。
做得非常好。我计划在本月晚些时候访问您的 jQuery 教程。
您是否知道是否有人提供使用 fittext 处理网格单元格(kendoui jquery 网格)内文本的示例?