有多种方法可以处理 javascript/jQuery 中的事件。其中两个是:
- 您可以在对象上使用直接事件处理程序。
- 您可以使用委托事件处理来处理父级上的传播事件。
如果您在对象上使用直接事件处理程序并且页面中没有配置委托事件处理程序,则没有理由e.stopPropagation()
.
但是,如果您有使用传播的委派事件处理程序,您有时需要确保更高级别的委派事件处理程序不会在当前事件上触发。
在你的具体例子中:
$(document.body).on('click', "a.ajaxLink", function(e){
这是一个委托事件处理程序。它正在寻找传播到的任何点击事件document.body
对象,但起源于a.ajaxLink
目的。在这里,优势不大e.stopPropagation()
因为事件几乎已经完全传播了(它也会上升到document
,但除非你还有一个处理程序click
on the 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()
and e.preventDefault()
。但是,如果您处于委托事件处理程序中,e.preventDefault()
不执行任何操作,因为当目标对象第一次看到该事件时,默认行为(如果有)已经触发。默认行为发生在事件传播之前,因此e.preventDefault()
仅适用于直接作用于目标对象的事件处理程序。
没有明显的性能下降,因为您允许事件冒泡,因为这些是用户级事件,并且它们发生的速度不够快,所以没有影响,当所有介入对象上没有处理程序时,冒泡特别慢。系统已经对某些事件进行了特殊处理,例如mousemove
这可以迅速解决该问题。如果您有一个包含数百或数千个事件处理程序的大型项目,则在某些情况下使用委托事件处理会更有效,而在实际目标对象上直接使用事件处理程序在某些情况下会更有效。但是,除了在巨大的场景中,性能差异可能并不明显。
这是一个冒泡/委托更有效的示例。您有一个包含数千行的巨大表格,每行都有两个按钮(例如添加/删除)。通过委派事件处理,您可以在附加到表对象(按钮的公共父级)的两个简单事件处理程序中处理所有按钮。这将比直接在每个按钮上安装数千个事件处理程序更快地安装事件处理程序。这些委托的事件处理程序还将自动处理表中新创建的行/对象。这是事件冒泡/委托事件处理程序的理想场景。请注意,在这种情况下,没有理由停止传播/冒泡。
下面是委托事件处理程序效率非常低的示例。假设您有一个大小合适的网页,其中包含数百个对象和事件处理程序。您可以使每个事件处理程序都成为附加到document
目的。但是,这就是发生的事情。发生咔嗒声。实际对象上没有事件处理程序,因此它会冒泡。最终,它到达文档对象。文档对象有数百个事件处理程序。事件处理引擎(本例中为 jQuery)必须查看每一个事件处理程序,并将每个事件处理程序的委托事件处理程序中的选择器与原始事件目标进行比较,看看它们是否匹配。其中一些比较速度并不快,因为它们可能是成熟的 CSS 选择器。它必须为数百个委托事件执行此操作。这对性能不利。这就是为什么.live()
jQuery 中的 已被弃用,因为它是这样工作的。相反,委托事件处理程序应尽可能靠近目标对象放置(在特定情况下,最接近的父对象)。而且,当不需要委托事件处理程序时,应将处理程序放在实际的目标对象上,因为这在运行时是最有效的。
回到你原来的问题。一般来说,您不希望关闭冒泡。正如我之前在回答中所描述的,在某些特定情况下,树上更远的事件处理程序想要处理该事件并阻止 DOM 树中更高层的任何委托事件处理程序处理此事件。那是时候了e.stopPropatation()
.
以下是其他几篇相关帖子,其中包含有关此主题的有用信息(因为之前已经广泛讨论过):
为什么不将 Javascript 事件委托发挥到极致呢? https://stackoverflow.com/questions/9711118/why-not-take-javascript-event-delegation-to-the-extreme/9711252#9711252
所有 jquery 事件都应该绑定到 $(document) 吗? https://stackoverflow.com/questions/12824549/should-all-jquery-events-be-bound-to-document/12824698#12824698
jQuery.on() 是否适用于创建事件处理程序后添加的元素? https://stackoverflow.com/questions/9814298/does-jquery-on-work-for-elements-that-are-added-after-the-event-handler-is-cre/9814409#9814409
jQuery on() 和 stopPropagation() https://stackoverflow.com/questions/11910735/jquery-on-and-stoppropagation/11910746#11910746
避免将大量 DOM 对象绑定到单击事件相关的内存或性能问题的最佳实践 https://stackoverflow.com/questions/15594663/best-practice-to-avoid-memory-or-performance-issues-related-to-binding-a-large-n/15595375#15595375
jQuery .live() 与 .on() 方法在加载动态 html 后添加点击事件 https://stackoverflow.com/questions/8752321/jquery-live-vs-on-method-for-adding-a-click-event-after-loading-dynamic-ht/8752376#8752376