javascript 冒泡_什么是JavaScript中的事件冒泡? 活动宣传说明

javascript 冒泡

事件冒泡是您在JavaScript旅行中可能遇到的一个术语。 它涉及一个元素嵌套在第二个元素内时事件处理程序被调用的顺序,并且两个元素都注册了同一事件的侦听器(例如,单击)。

但是事件冒泡只是难题的一部分。 通常将其与事件捕获和事件传播一起提及。 对这三个概念的深刻理解对于使用JavaScript处理事件至关重要-例如,如果您希望实现事件委托模式

在这篇文章中,我将解释这些术语中的每一个,并演示它们如何组合在一起。 我还将向您展示对JavaScript事件流的基本了解如何为您提供对应用程序的细粒度控制。 请注意,这不是事件的入门,因此假设您已熟悉该主题。 如果您想了解一般事件的更多信息,为什么不阅读我们的书: JavaScript:Ninja的新手

什么是事件传播?

让我们从事件传播开始。 这是事件冒泡和事件捕获的总称。 考虑典型的标记以建立链接图像列表,例如,缩略图库:

<ul>
    <li><a href="..."><img src="..." alt=""></a>
    <li><a href="..."><img src="..." alt=""></a>
    ...
    <li><a href="..."><img src="..." alt=""></a>
</ul>

单击图像不仅会为相应的IMG元素生成click事件,还会为父级A ,祖父LI等等生成click事件,一直到元素的所有祖先,直到终止于window对象为止。

在DOM术语中,图片是事件目标 ,即点击所基于的最内层元素。 事件目标及其祖先,从其父节点一直到window对象,在DOM树中形成一个分支。 例如,在图片库中,此分支将由以下节点组成: IMGALIULBODYHTMLdocumentwindow

请注意, window实际上不是DOM节点,而是实现了EventTarget接口,因此,为简单起见,我们将其作为文档对象的父节点来处理。

该分支很重要,因为它是事件传播(或流动)的路径。 这种传播是为给定事件类型调用所有侦听器的过程,该事件类型附加到分支上的节点。 每个侦听器将被一个event对象调用,该对象收集与event有关的信息(稍后会对此进行更多介绍)。

请记住,可以在同一事件类型的节点上注册多个侦听器。 当传播到达一个这样的节点时,将按照其注册顺序调用侦听器。

还应注意,分支确定是静态的,也就是说,它是在事件的初始派发时建立的。 事件处理期间发生的树修改将被忽略。

从窗口到事件目标再向后传播是双向的。 这种传播可以分为三个阶段:

  1. 从窗口到事件目标父对象:这是捕获阶段
  2. 事件目标本身:这是目标阶段
  3. 从事件目标父级回到窗口: 气泡阶段

这些阶段的区别在于所调用的侦听器的类型。

事件捕获阶段

在此阶段,仅调用捕获器侦听器,即使用addEventListener的第三个参数的true值注册的那些侦听器:

el.addEventListener('click', listener, true)

如果省略此参数,则其默认值为false,并且侦听器不是捕获器。

因此,在此阶段中,仅调用从窗口到事件目标父对象的路径中找到的捕获器。

活动目标阶段

在此阶段,将调用在事件目标上注册的所有侦听器,无论其捕获标志的值如何。

事件冒泡阶段

在事件冒泡阶段,仅非捕获者将被调用。 也就是说,仅监听器为addEventListener()的第三个参数注册了false值:

el.addEventListener('click', listener, false) // listener doesn't capture
el.addEventListener('click', listener) // listener doesn't capture

请注意,尽管所有事件都随着捕获阶段, focusblurload和其他一些事件流入事件目标,但不要冒泡。 也就是说,他们的旅行在目标阶段之后停止。

因此,在传播结束时,分支上的每个侦听器仅被调用一次。

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

事件冒泡并不会针对每种事件发生。 在传播期间,侦听器可以通过读取event对象的.bubbles布尔属性来了解事件是否冒泡。

下图显示了W3C UIEvents规范中的三个事件流阶段。

事件冒泡:使用DOM事件流在DOM树中调度的事件的图形表示

版权所有©2016万维网联盟(MIT,ERCIM,京王,北航)

访问传播信息

我已经提到了event对象的.bubbles属性。 此对象提供了许多其他属性,供侦听器用来访问有关传播的信息。

  • e.target引用事件目标。
  • e.currentTarget是在其上注册正在运行的侦听器的节​​点。 这是与侦听器调用上下文相同的值,即this关键字引用的值。
  • 我们甚至可以使用e.eventPhase找出当前阶段。 它是指一个三个整数Event构造常量CAPTURING_PHASEBUBBLING_PHASEAT_TARGET

付诸实践

让我们将上述概念付诸实践。 在下面的笔中,有五个嵌套的方形框,名为b0b4 。 最初,只有外部框b0是可见的; 当鼠标指针悬停在上方时,将显示内部。 当我们单击一个框时,传播流的日志显示在右表中。

请参阅CodePen上的SitePoint( @SitePoint )的Pen jmXdpz

甚至可以在框外单击:在这种情况下,事件目标将是BODYHTML元素,具体取决于单击屏幕的位置。

停止传播

通过调用事件对象的stopPropagation方法,可以在任何侦听器中停止事件传播。 这意味着将不会调用在传播路径上跟随当前目标的节点上注册的所有侦听器。 相反,当前目标上附加的所有其他其余侦听器仍将接收该事件。

我们可以使用上一个演示简单fork来检查此行为,只需在其中一个stopPropagation()插入对stopPropagation()的调用即可。 在这里,我们将这个新的侦听器作为捕获器添加到window注册的回调列表的前面:

window.addEventListener('click', e => { e.stopPropagation(); }, true);
window.addEventListener('click', listener('c1'), true);
window.addEventListener('click', listener('c2'), true);
window.addEventListener('click', listener('b1'));
window.addEventListener('click', listener('b2'));

这样,无论单击什么框,传播都会提前停止,仅到达window上的捕获器侦听window

停止立即传播

如其名称所示, stopImmediatePropagation立即停止刹车,甚至阻止当前侦听器的同级接收该事件。 我们可以看到这与最后一支笔最小变化

window.addEventListener('click', e => { e.stopImmediatePropagation(); }, true);
window.addEventListener('click', listener('c1'), true);
window.addEventListener('click', listener('c2'), true);
window.addEventListener('click', listener('b1'));
window.addEventListener('click', listener('b2'));

现在,日志表中没有任何输出, c1c2窗口捕获器行也没有输出,因为传播在执行新侦听器后停止。

活动取消

某些事件与浏览器在传播结束时执行的默认操作相关联。 例如,单击链接元素或单击表单提交按钮会使浏览器导航到新页面或分别提交表单。

通过在侦听器中调用事件对象的另一种方法e.preventDefault可以避免通过事件取消执行此类默认操作。

结论

借此,我希望向您展示了事件冒泡和事件捕获在JavaScript中是如何工作的。 如果您有任何问题或意见,我们很高兴在下面的讨论中听到他们的意见。

参考资料

Yaphi BerhanuDominic Myers 对此文章进行了同行评审。 感谢所有SitePoint的同行评审员使SitePoint内容达到最佳状态!

翻译自: https://www.sitepoint.com/event-bubbling-javascript/

javascript 冒泡

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值