真实世界的例子,其中事件捕获是必要的/首选的



addEventListener DOM方法支持第三个可选的布尔参数(useCapture),用于指示函数应该使用事件冒泡还是事件捕获作为传播方法。在本文中,很好地展示了两者的区别(单击示例&视图代码)。

从其他关于SO和博客文章的问题中,我得出结论,事件冒泡主要是因为IE8不支持它。

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

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

这两个当时重要的浏览器的主要区别之一是处理事件的方式。微软使用冒泡泡阶段——这意味着事件首先击中目标元素,然后向上遍历整个DOM击中父节点,而Netscape则采用完全相反的方式——这意味着事件首先传递父元素,然后向下运行到目标元素——捕获。这在早期给开发人员带来了很多麻烦,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

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

捕获阶段的机制使其非常适合准备或防止稍后将在冒泡阶段由事件委托应用的行为。这就是我们在这里使用它的方式——在响应鼠标点击时初始化可排序对象,但要在事件开始冒泡和其他处理程序有机会处理它之前。

为了利用捕获,我们必须深入到金属中。jQuery的事件方法只适用于冒泡,不允许我们进入捕获阶段。捕获处理程序看起来像:

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

引用

  • Domina Github Repo: Readme - Event Propagation

  • EmberJS RFC: Capture Based events

  • EmberJS RFC: Internet Explorer

  • MDN: Event.eventPhase

  • 使用事件捕获来提高Basecamp页面加载时间-信号与噪声

  • 冒泡,外部事件和Firefox: Index

  • 事件捕获和冒泡

相关内容

  • 没有找到相关文章

最新更新