在JavaScript/jQuery中,有几种处理事件的方法。其中两种是:
- 你可以在对象上使用直接事件处理程序。
- 你可以使用委托事件处理,其中你在父级上处理传播事件。
如果你在对象上使用直接事件处理程序,并且页面中没有配置委派事件处理程序,则没有理由使用 e.stopPropagation()
。
但是,如果你有使用传播的委托事件处理程序,有时你会想确保更高级别的委派事件处理程序不会在当前事件上触发。
在你的特定示例中:
$(document.body).on('click', "a.ajaxLink", function(e){
这是一个委托事件处理程序。它寻找任何传播到 document.body 对象上的 click 事件,但起源于 a.ajaxLink 对象。这里,在大部分事件已经传播的情况下,e.stopPropagation() 几乎没有优势(它也会传播到 document 上,但除非您还在 document 对象上有一个 click 处理程序,否则在此处理程序中没有理由使用 e.stopPropagation())。
当您既有顶级委派事件处理程序(如您示例中的处理程序),又有较低级别的事件处理程序(直接在对象上或使用委派事件处理,但在 document.body 对象以下的级别)时,它就有很多意义。在这种情况下,如果您只想让较低级别的事件处理程序获取事件,则会在其处理程序中调用 e.stopPropagation(),以便 document.body 处理程序永远不会看到该事件。
$("a.ajaxLink").click(function(e) {
if (some condition) {
code here
e.stopPropagation();
}
})
注意:在 jQuery 的事件处理程序中使用 `return false` 会触发 `e.stopPropagation()` 和 `e.preventDefault()`。但是,如果您在委托的事件处理程序中,则 `e.preventDefault()` 不起作用,因为默认行为(如果有)已在目标对象首次看到事件时触发。默认行为发生在事件传播之前,因此 `e.preventDefault()` 仅在直接放置在目标对象上的事件处理程序中起作用。
没有明显的性能下降,因为您允许事件冒泡,因为这些是用户级事件,它们不会发生得足够快以至于无法处理,而且当所有中间对象都没有处理程序时,冒泡速度也不会特别慢。系统已经对一些可能会快速发生的事件(如 `mousemove`)进行了特殊处理来解决这个问题。如果您有一个包含数百或数千个事件处理程序的巨大项目,则使用委托事件处理可能更有效率,而在实际目标对象上使用直接事件处理程序可能更有效率。但是,除了在巨大场景中,性能差异可能并不明显。
以下是冒泡/委托更有效的示例。您有一个包含数千行的巨型表格,每行都有两个按钮(添加/删除)。使用委派事件处理程序,您可以将所有按钮都处理为两个简单的事件处理程序,将它们附加到表格对象(按钮的公共父级)。这样安装事件处理程序会比在每个按钮上直接安装几千个事件处理程序快得多。这些委托事件处理程序还将自动在表格中新创建的行/对象上工作。这是事件冒泡/委派事件处理程序的理想情况。请注意,在此场景中,没有理由停止传播/冒泡。
以下是委派事件处理程序非常低效的示例。假设您有一个规模不小的网页,其中包含数百个对象和事件处理程序。您可以使每个事件处理程序都成为附加到 `document` 对象的委托事件处理程序。但是,下面是会发生的事情。单击发生。实际对象上没有事件处理程序,因此它会冒泡上来。最终,它到达了 `document` 对象。`document` 对象有数百个事件处理程序。事件处理引擎(在这种情况下是 jQuery)必须查看每个委托事件处理程序中的选择器与原始事件目标是否匹配。这些比较中的某些可能不太快,因为它们可以是完整的 CSS 选择器。必须对数百个委托事件进行此操作。这对性能不利。这正是为什么在 jQuery 中 `live()` 被弃用的原因,因为它以这种方式工作。相反,应该尽可能靠近目标对象放置委托事件处理程序(给定情况下最接近的父级),并且当没有需要委派的事件处理程序时,应将处理程序放在实际目标对象上,因为这是运行时最有效率的。
回到您最初的问题。通常情况下,没有时间希望气泡被关闭。正如我在之前的答案中所描述的那样,有特定的情况,其中树形结构上更远处的事件处理程序想要处理该事件并停止任何委托给DOM树中更高级别的事件处理程序来处理此事件的情况。这是调用e.stopPropatation()
的时候。
以下是一些相关的帖子,它们提供了有关此主题的有用信息(因为此话题已经被广泛讨论):
为什么不将JavaScript事件委派推向极致?
是否应将所有jQuery事件绑定到$(document)?
jQuery.on()对于在创建事件处理程序之后添加的元素是否有效?
jQuery on()和stopPropagation()
避免绑定大量DOM对象以进行单击事件而导致的内存或性能问题的最佳实践
jQuery.live()与.on()方法在加载动态html后添加单击事件的区别
return false
,它已经停止了事件传播... - kapa<body>
。 - tim peterson