事件捕获是必要/首选的真实世界示例?

时间:2014-07-16 17:11:38

标签: javascript requirements dom-events event-propagation event-capturing

addEventListener DOM方法支持第三个可选的布尔参数(useCapture)来指示函数是否应使用事件冒泡或事件捕获作为传播方法。在this article中,很好地显示了差异(点击示例和视图代码)。

从SO和博客文章的其他问题来看,我认为事件冒泡主要是因为IE8-不支持它。

假设我只需要支持IE9 +,在什么情况下事件捕获对于事件冒泡是必要的还是首选的?换句话说,在什么情况下最好让事件首先在最外面的元素上执行,然后在最里面的元素上执行?我正在寻找一个简单的,真实世界的例子来演示事件捕获的使用......

1 个答案:

答案 0 :(得分:2)

事件捕获曾经是Internet Explorer浏览器之外的唯一选项:

  

当时两个重要浏览器的主要区别之一是他们如何处理事件。 Microsoft使用冒泡阶段 - 意味着事件首先传递父元素,然后向下运行到目标元素。 Netscape以其他方式完成它 - 并且事件首先命中目标元素,然后遍历整个DOM向上命中父节点 - 捕获。这导致开发人员在早期遇到很多麻烦,而W3C最终指定了一种方法,在这种方法中,两种工作方式都可以免费使用。

当不支持冒泡时,事件捕获在事件委派中很有用。例如:

  

某些事件,例如焦点,不会冒泡,但可以捕获。   目标元素上的内联处理程序在目标元素的捕获处理程序之前触发。

     

Web平台中的许多新指定的事件(例如媒体事件)都没有冒泡,这对依赖于事件委派的Ember这样的框架来说是一个问题。但是,在IE9中添加的捕获API可以针对所有事件正确调用,并且不需要规范化层。支持捕获API不仅允许我们删除jQuery依赖项,而且它将允许我们正确处理这些非冒泡事件。这将允许您使用诸如在组件中播放之类的事件,而无需手动设置事件侦听器。

自定义事件和冒泡有以下问题:

  

目前,Ember依赖于jQuery进行事件处理,这样做会带来几个成本:

jQuery silently changes inline handlers to bubble handlers.
    This changes expected invocation order
    This can cause automated tests to fail
Events triggered via jQuery.trigger trigger handlers in a different order than events triggered by a user.
    This changes expected invocation order
    This leads to difficult to reason about and debug aberrations in behavior
    This often causes automated tests to fail
Events must flow down and bubble back up through the entire DOM before being detected by the Ember application, and then must undergo an expensive delegation process that is effectively re-bubbling to find the right handler.
Handlers attached directly within components or by non-ember plugins take precedent over handlers attached by Ember, whether this was desired or not.

    This causes component handlers to have far-reaching side-effects
    This leads to difficult to reason about and debug aberrations in behavior
    This often causes automated tests to fail

媒体播放器焦点=>播放预处理/后处理事件流将是一个简单的用例。

  

捕获阶段的机制使其成为准备或防止随后在冒泡阶段由事件委派应用的行为的理想选择。这就是我们在这里使用它的方式 - 初始化可点击以响应鼠标点击,但就在事件开始冒泡之前,其他处理程序有机会处理它。

     

为了利用捕获,我们必须归结为金属。 jQuery的事件方法只适用于冒泡,不要让我们进入捕获阶段。捕获处理程序如下所示:

    document.addEventListener("mousedown", function(event) {
      if ($(event.target).closest(".sortable_handle").length) {
         $("article.todolist, section.todolists").sortable();
         }
      }, true);

<强>参考