有几种方法可以处理 javascript/jQuery 中的事件。其中两个是:
- 您可以在对象上使用直接事件处理程序。
- 您可以使用委托事件处理来处理父级上的传播事件。
如果您在对象上使用直接事件处理程序并且页面中没有配置委托事件处理程序,则没有理由使用e.stopPropagation()
.
但是,如果您有使用传播的委托事件处理程序,您有时需要确保更高级别的委托事件处理程序不会在当前事件上触发。
在您的特定示例中:
$(document.body).on('click', "a.ajaxLink", function(e){
这是一个委托事件处理程序。它正在寻找任何传播到document.body
对象但起源于a.ajaxLink
对象的点击事件。在这里,几乎没有什么好处,因为事件几乎已经e.stopPropagation()
完全传播(它也会上升到document
click
document
e.stopPropagation()
当您同时拥有顶级委托事件处理程序(如示例中的事件处理程序)和较低级别的事件处理程序(直接在对象上或使用委托事件处理,但在低于document.body
对象的级别。在这种情况下,如果您只希望较低级别的事件处理程序获取事件,那么您将调用e.stopPropagation()
它的处理程序,以便document.body
处理程序永远不会看到事件。
$("a.ajaxLink").click(function(e) {
if (some condition) {
// do something specific to this condition
code here
// stop propagation so the default behavior for click in document.body does not fire
e.stopPropagation();
}
})
注意:使用return false
jQuery 事件处理程序会同时触发e.stopPropagation()
和e.preventDefault()
。但是,如果您在委托的事件处理程序中,e.preventDefault()
则不会做任何事情,因为默认行为(如果有的话)在目标对象第一次看到事件时已经触发。默认行为发生在事件传播之前,因此e.preventDefault()
仅适用于直接在目标对象上的事件处理程序。
没有明显的性能下降,因为您允许事件冒泡,因为这些是用户级别的事件,并且它们发生的速度不够快,并不重要,当所有干预对象上都没有处理程序时,冒泡并不是特别慢。该系统已经是特殊情况,一些类似mousemove
的事件可以迅速发生以解决该问题。如果您有一个包含数百或数千个事件处理程序的大型项目,那么在某些情况下使用委托事件处理会更有效,而在实际目标对象上直接事件处理程序会更有效。但是,除了在巨大的场景中,性能差异可能并不明显。
这是一个冒泡/委托更有效的示例。您有一个包含数千行的巨型表格,每行中有两个按钮(例如添加/删除)。通过委托事件处理,您可以处理附加到表对象(按钮的公共父级)的两个简单事件处理程序中的所有按钮。安装事件处理程序比直接在每个按钮上安装数千个事件处理程序要快得多。这些委托的事件处理程序也将自动处理表中新创建的行/对象。这是事件冒泡/委托事件处理程序的理想方案。请注意,在这种情况下,没有理由停止传播/冒泡。
这是一个委托事件处理程序效率非常低的示例。假设您有一个包含数百个对象和事件处理程序的大小合适的网页。您可以使每个事件处理程序都成为附加到document
目的。但是,这就是发生的事情。点击发生。实际对象上没有事件处理程序,因此它会冒泡。最终,它到达了文档对象。文档对象有数百个事件处理程序。事件处理引擎(本例中为 jQuery)必须查看每一个事件处理程序,并将每个事件处理程序的委托事件处理程序中的选择器与原始事件目标进行比较,以查看它们是否匹配。其中一些比较并不快,因为它们可以是成熟的 CSS 选择器。它必须为数百个委托事件执行此操作。这对性能不利。这正是为什么.live()
在 jQuery 中已被弃用,因为它以这种方式工作。相反,委托的事件处理程序应尽可能靠近目标对象(在特定情况下可行的最接近的父对象)。而且,当不需要委托事件处理程序时,应将处理程序放在实际的目标对象上,因为这在运行时是最有效的。
回到你原来的问题。没有时间通常要关闭冒泡。正如我在前面的回答中所描述的,在某些特定情况下,树上更远的事件处理程序想要处理事件并阻止 DOM 树中更高层的任何委托事件处理程序处理此事件。那是时候了e.stopPropatation()
。
以下是其他几篇相关文章,其中包含有关此主题的有用信息(正如之前已广泛讨论的那样):
为什么不将 Javascript 事件委托发挥到极致呢?
所有 jquery 事件都应该绑定到 $(document) 吗?
jQuery.on() 是否适用于在创建事件处理程序后添加的元素?
jQuery on() 和 stopPropagation()
避免与将大量 DOM 对象绑定到单击事件相关的内存或性能问题的最佳实践
jQuery .live() 与 .on() 方法在加载动态 html 后添加点击事件