使用e.stopPropagation()来防止事件冒泡的利弊

tim*_*son 6 javascript jquery javascript-events event-bubbling stoppropagation

很多人都解释说e.stopPropagation()可以防止事件冒泡.但是,我很难找到为什么人们想要或者想要首先阻止事件冒泡.

在我的网站上,我有许多元素,如下所示:

$(document.body).on('click', ".clickable", function(e){ 
   //e.stopPropagation();
  //do something, for example show a pop-up or click a link   
});

<body>
  <p>outside stuff</p>
  <button type="button" class='clickable'>
    <img src='/icon.jpg'> Do Something

  </button>
</body>
Run Code Online (Sandbox Code Playgroud)

我想添加e.stopPropagation()因为我想要将事件处理程序更改'touch''click'使用这个真棒触摸库Hammer.js..这将允许点击在桌面上正常发生以及在移动设备上进行触摸事件.

这个问题(请纠正我,如果我错了)是触摸设备上的滚动减慢停止.

e.stopPropgation()有用吗?这样,无论何时触摸屏幕 - document.body事件冒泡都不会每次都发生?

jfr*_*d00 12

有几种方法可以处理javascript/jQuery中的事件.其中两个是:

  1. 您可以在对象上使用直接事件处理程序.
  2. 您可以使用委派事件处理来处理父项上的传播事件.

如果您在对象上使用直接事件处理程序,并且页面中没有配置委派的事件处理程序,则没有理由e.stopPropagation().

但是,如果您已委派使用传播的事件处理程序,则有时需要确保更高级别的委托事件处理程序不会触发当前事件.

在您的特定示例中:

$(document.body).on('click', "a.ajaxLink", function(e){ 
Run Code Online (Sandbox Code Playgroud)

这是一个委托的事件处理程序.它正在寻找任何传播到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();
    }
})
Run Code Online (Sandbox Code Playgroud)

注意:使用return falsejQuery事件处理程序会触发e.stopPropagation()e.preventDefault().但是,如果您在委托事件处理程序中,e.preventDefault()则不会执行任何操作,因为当目标对象第一次看到事件时,已经触发了默认行为(如果有的话).默认行为发生在事件传播之前,因此e.preventDefault()仅在事件处理程序中直接在目标对象上起作用.


没有明显的性能下降,因为您允许事件冒泡,因为这些是用户级事件,并且它们发生的速度不够快,而且当所有干预对象上没有处理程序时,冒泡特别慢.系统已经是特殊情况,这样的一些事件mousemove可以迅速解决这个问题.如果您有一个包含数百或数千个事件处理程序的巨型项目,则有时使用委派事件处理更有效,并且有些情况下实际目标对象上的直接事件处理程序更有效.但是,除了在巨大的场景中,性能差异可能并不明显.

这是一个鼓泡/委托更有效的例子.你有一个包含数千行的巨型表,每行有两个按钮(添加/删除说).通过委派事件处理,您可以处理附加到表对象的两个简单事件处理程序中的所有按钮(按钮的公共父级).这将更快地安装事件处理程序,而不是直接在每个按钮上安装数千个事件处理程序.这些委派的事件处理程序也将自动处理表中新创建的行/对象.这是事件冒泡/委托事件处理程序的理想方案.请注意,在这种情况下,没有理由停止传播/冒泡.

以下是委托事件处理程序效率非常低的示例.假设您有一个包含数百个对象和事件处理程序的大型Web页面.您可以使每个事件处理程序都是附加到该document对象的委托事件处理程序.但是,这就是发生的事情.点击发生.实际对象上没有事件处理程序,因此它会冒泡.最终,它到达文档对象.文档对象有数百个事件处理程序.事件处理引擎(在本例中为jQuery)必须查看每个事件处理程序,并将委托事件处理程序中的选择器与原始事件目标进行比较,以查看它们是否匹配.其中一些比较并不快,因为它们可以是完整的CSS选择器.它必须为数百个委派事件做到这一点.这对性能不利.这正是.live()jQuery被弃用的原因,因为它以这种方式工作.相反,委托事件处理程序应尽可能靠近目标对象放置(根据具体情况,最接近的父对象).并且,当不需要委托事件处理程序时,处理程序应该放在实际的目标对象上,因为这在运行时是最有效的.


回到原来的问题.没有时间你想要一般关闭冒泡.正如我在前面的回答中所描述的那样,有一些特定的实例,树上的事件处理程序想要处理事件并阻止DOM树中更高级别的任何委托事件处理程序处理此事件.那是一个时间e.stopPropatation().


以下是其他几个相关帖子,其中包含有关此主题的有用信息(之前已广泛讨论过):

为什么不把Javascript事件委托带到极致?

是应该将所有jquery事件绑定到$(文档)?

jQuery.on()是否适用于在创建事件处理程序后添加的元素?

jQuery on()和stopPropagation()

避免与将大量DOM对象绑定到click事件相关的内存或性能问题的最佳实践

jQuery .live()vs .on()方法,用于在加载动态html后添加click事件


归档时间:

查看次数:

6623 次

最近记录:

8 年,1 月 前