使用e.stopPropagation()来防止事件冒泡的利弊 [英] Pros and Cons of using e.stopPropagation() to prevent event bubbling

查看:140
本文介绍了使用e.stopPropagation()来防止事件冒泡的利弊的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Many people have explained that e.stopPropagation() prevents event bubbling. However, I'm having a hard time finding why one would want or want to prevent event bubbling in the first place.

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

On my site I have many elements which are called like this:

$(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>

我想添加 e.stopPropagation()因为我想使用'touch'从'click' http://eightmedia.github.io/hammer.js/\">这个很棒的触摸库,Hammer.js。。这将允许点击在桌面上正常发生以及在移动设备上进行触摸事件。

I was thinking to add e.stopPropagation() because I want to change the event handler to 'touch' from 'click' using this awesome touch library, Hammer.js.. This would allow for clicking to happen normally on desktop and for touch events on mobile devices.

这个问题(如果我错了请纠正我)是滚动在触摸设备上减速停止。

The problem with this (please correct me if I'm wrong) is that scrolling on touch devices slows to a halt.

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

Is this where e.stopPropgation() is useful? Such that whenever one touches the screen document.body-event bubbling is NOT happening every time?

推荐答案

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

There are several ways you can handle events in javascript/jQuery. Two of them are:


  1. 您可以在对象上使用直接事件处理程序。

  2. 您可以使用委托事件处理来处理父项上的传播事件。

如果在对象上使用直接事件处理程序,在页面中没有配置任何委托事件处理程序,那么 e.stopPropagation()没有理由。

If you are using a direct event handler on the object and there are no delegated event handlers configured in the page, then there is no reason for e.stopPropagation().

但是,如果您委派了正在使用传播的事件处理程序,您有时希望确保更高级别的委托事件处理程序不会触发当前事件。

But, if you have delegated event handlers that are using propagation, you sometimes want to make sure that a higher level delegated event handler does not fire on the current event.

在您的特定示例中:

$(document.body).on('click', "a.ajaxLink", function(e){ 

这是一个委托的事件处理程序。它正在查找传播到的任何点击事件 document.body 对象,但它起源于 a.ajaxLink 对象。这里, e.stopPropagation()因为事件几乎已经完全传播(它也会上升到文档,但除​​非你也有的处理程序在文档对象上单击,然后没有理由 e.stopPropagation( )在这个处理程序中。

This is a delegated event handler. It is looking for any click event that propagates up to the document.body object, yet originated on an a.ajaxLink object. Here, there is little advantage to e.stopPropagation() because the event is almost entirely propagated already (it will also go up to the document, but unless you also have a handler for click on the document object, then there's no reason to e.stopPropagation() in this handler.

当你同时拥有一个顶级委托事件处理程序时(如您的示例中有一个)并且您具有较低级别的事件处理程序(直接在对象上或使用委托事件处理,但在 document.body 对象之下的级别。在这种情况下,如果您只想让较低级别的事件处理程序获取事件,那么您可以在它的处理程序中调用 e.stopPropagation(),以便 document.body 处理程序从未见过该事件。

Where it would make a lot of sense would be when you have both a top level delegated event handler (like the one in your example) and you have lower level event handlers (either directly on the objects or using delegated event handling, but at a level below the document.body object. In that case, if you only want the lower level event handler to get the event, then you would call e.stopPropagation() in it's handler so that the document.body handler never saw the event.

$("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();
    }
})

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

Note: Using return false from a jQuery event handler triggers both e.stopPropagation() and e.preventDefault(). But, if you are in a delegated event handler, the e.preventDefault() doesn't do anything because the default behavior (if there was one) has already fired when the target object first saw the event. Default behaviors happen before event propagation so e.preventDefault() only works in event handlers directly on the target object.

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

There is no noticeable performance degradation because you allow an event to bubble up because these are user level events and they just don't occur fast enough to matter, not is the bubbling particularly slow when there are no handlers on all the intervening objects. The system already special cases some events like mousemove that can happen rapidly to solve that issue. If you have a giant project with hundreds or thousands of event handlers, there are cases where using delegated event handling is more efficient and there are cases where direct event handlers on the actual target objects are more efficient. But, except in giant scenarios, the performance difference is probably not noticeable.

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

Here's an example where bubbling/delegation is more efficient. You have a giant table with thousands of rows and each row has two buttons in it (add/delete say). With delegated event handling, you can handle all the buttons in two simple event handlers that you attach to the table object (a common parent of the buttons). This will be much quicker to install the event handlers rather than installing several thousand event handlers directly on each and every button. These delegated event handlers will also automatically work on newly created rows/objects in the table. This is the ideal scenario for event bubbling/delegated event handlers. Note, in this scenario, there is no reason to stop propagation/bubbling.

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

Here's an example of where delegated event handlers are very inefficient. Supposed you have a good-sized web page with hundreds of objects and event handlers. You could make every one of the event handlers be a delegated event handler attached to the document object. But, here's what happens. A click happens. There's no event handler on the actual object so it bubbles up. Eventually, it gets to the document object. The document object has hundreds of event handlers. The event processing engine (jQuery in this case) has to look through every one of those event handlers and compare the selector in the delegated event handler for each one with the original event target to see if they match. Some of these comparisons are not fast as they can be full-blown CSS selectors. It has to do that for hundreds of delegated events. This is bad for performance. This is exactly why .live() in jQuery was deprecated because it worked this way. Instead, delegated event handlers should be placed as close to the target object as possible (the closest parent that is practical given the circumstances). And, when there is no need for a delegated event handler, handlers should be put on the actual target object as this is the most efficient at runtime.

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

Back to your original question. There is no time that you want bubbling turned off generally. As I described earlier in my answer, there are specific instances where an event handler further out on the tree wants to handle the event and stop any delegated event handlers higher up in the DOM tree from processing this event. That is a time to e.stopPropatation().

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

Here are several other relevant posts with useful info on this topic (as it has been widely discussed before):

为什么不将Javascript事件授权推向极致?

是否应绑定所有jquery事件到$(文件)?

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

jQuery on()和stopPropagati on()

避免与将大量DOM对象绑定到点击事件相关的内存或性能问题的最佳做法

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

这篇关于使用e.stopPropagation()来防止事件冒泡的利弊的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆