考虑这么个例子:

<div><button id="btn">Click Me!</button> </div> 

哪怕一个web开发的初学者都会知道,当我们鼠标在button上点击时,会在button上触发一个click事件。但是:

  • button是div的一个子Node;从界面上来看,在button里点击相当于在div里点击;那click事件也会触发在div上吗?
  • 如果click事件也触发在div上,那它们会不会共用同一个事件对象?
  • 如果click事件也触发在div上,谁的事件会先发生?
  • click事件还会在哪些元素上面触发?
  • 等等...

想解答上述问题,我们需要理解事件(Event)一个很重要的机制:事件流动(Event Flow)。

事件流动

DOM事件不单单只会在一个Element上触发,它还会流向其他Element。事件的流动通常会经历这么三个阶段:

捕获阶段 -> 目标阶段 -> 冒泡阶段

"eventPhase"

“eventPhase”是“Event”下的一个属性,它指明当前event属于那一个阶段。
“eventPhase”可能是一下其中一个值:

  • Event.NONE,0,没有事件需要处理
  • Event.CAPTURING_PHASE,1,捕获阶段
  • Event.AT_TARGET,2,目标阶段,事件对象到达事件目标上
  • Event.BUBBLING_PHASE,3,冒泡阶段

下面我们详细讨论一下这三个阶段。

捕获阶段(capture phase)

捕获阶段的定义如下(w3c):

The event object propagate through the target's ancestors from the defaultView to the target's parent.
事件对象在事件目标的祖先中上到下顺向传播,从最顶层的defaultView到事件目标的(直系)父元素。

捕获阶段发生在整个事件流动的开始。在这阶段里事件会从父(主干)到子(分支)由上往下传播,被元素一层层地捕获。
文章开头的例子里面,捕获阶段的click事件会依次在document、body、div上触发:

document    1v
body    2v
div    3 v button 

一般我们没太大需要监听捕获阶段的事件;如果你确实希望这么做,需要将addEventListener的第三个参数设置为true:

// 第三个参数设置是否为捕获阶段,默认为false
element.addEventListener('click', function() {}, true) 

目标阶段(target phase)

目标阶段的定义是(w3c):

The event object arrive at the event object's event target.
事件对象到达事件目标。

例子里面,就是事件在button上触发的。addEventListener可以监听目标阶段的事件:

element.addEventListener('click', function() {}) 

如果事件是不可冒泡的,那整个事件流动会到此为止,不会发生下面的冒泡阶段。

冒泡阶段(bubble phase)

冒泡阶段的定义如下(w3c):

The event object propagates through the target's ancestors in reverse order, starting with the target's parent and ending with the defaultView.
事件对象会在事件目标的祖先元素里反向传播,由开始的父元素到最后的defaultView(document)。

冒泡阶段发生在最后,这也是我们最为熟悉的一个阶段。在这阶段里事件会从子(分支)到父(主干)逆向传播,看起来像是一个水里的泡泡往上冒。
例子里面,冒泡阶段的click事件会依次在div、body、document上触发:

document    3^
body    2^
div    1 ^ button 

"bubbles"

Event下的bubbles属性标明该事件是否为可冒泡的。一旦该值为false,则说明 evnet不可冒泡,那其流动也会在第二阶段“目标阶段”后就终止。


总结

若一个元素(div)是目标元素(button)的祖先,那事件对象会在该元素上触发两次:一次是捕获阶段(1)的,另一次是冒泡阶段(3)的。当事件对象在事件目标元素(button)上触发时,事件流动进入了目标阶段(2)。

  • 想监听捕获阶段的事件,可以这样:element.addEventListener('click', cb, true),将第三个参数设置为true。
  • 想监听冒泡阶段的事件,可以这样:element.addEventListener('click', cb,),不使用第三个参数或将其设置为false。
  • 而上述的任何一种监听方式都可以监听到目标阶段的事件。

最后,你可以配合这个例子来确认一下你的理解。

      let divElement = document.querySelector('div')let btnElement = document.querySelector('button') document.body.addEventListener('click', event => { console.log('Body Click in Bubble Phase.') console.log('Event Phase: ' + event.eventPhase) }) document.body.addEventListener('click', event => { console.log('Body Click in Capture Phase.') console.log('Event Phase: ' + event.eventPhase) }, true) divElement.addEventListener('click', event => { console.log('Div Click in Bubble Phase.') console.log('Event Phase: ' + event.eventPhase) }) divElement.addEventListener('click', event => { console.log('Div Click in Capture Phase.') console.log('Event Phase: ' + event.eventPhase) }, true) btnElement.addEventListener('click', event => { console.log('Button Click in Target Phase.') console.log('Event Phase: ' + event.eventPhase) }) btnElement.addEventListener('click', event => { console.log('Button Click in Target Phase.') console.log('Event Phase: ' + event.eventPhase) }, true) 
Body Click in Capture Phase.
Event Phase: 1
Div Click in Capture Phase.
Event Phase: 1
Button Click in Target Phase.
Event Phase: 2
Button Click in Target Phase.
Event Phase: 2
Div Click in Bubble Phase. Event Phase: 3 Body Click in Bubble Phase. Event Phase: 3

作者:butterandfly
链接:https://www.jianshu.com/p/382895a4027d
來源:简书

转载于:https://www.cnblogs.com/Yehudic/p/10139752.html

Event flow相关推荐

  1. WebKit DOM Event (一)

    DOM Event 规范 DOM Event 主要定义了三类接口: EventTarget, 所有DOM节点和XMLHttpRequest 都实现EventTarget接口 class EventTa ...

  2. What is event bubbling and capturing?

    What is event bubbling and capturing? 答案1 Event bubbling and capturing are two ways of event propaga ...

  3. DPDK 报文调度/保序 终极解决方案 Event Dev 简介(硬件加速也很可能是鸿蒙微内核IPC性能的钥匙)...

    01 背景介绍 网络报文的分发以及保序一直以来是让人头痛的问题, 为了完整的解释Event Dev的背景,我们可以从两个基本概念的定义开始: 报文分发是指针对网络通信报文的某种特征(例如 5 tupl ...

  4. netty4.0.x源码分析—bootstrap

    Bootstrap的意思就是引导,辅助的意思,在编写服务端或客户端程序时,我们都需要先new一个bootstrap,然后基于这个bootstrap调用函数,添加eventloop和handler,可见 ...

  5. ActionScript 3.0 Step By Step系列(六):学对象事件模型,从点击按扭开始

    事件可以理解为所发生的.ActionScript 能够识别并可响应的事情.许多事件与用户交互有关 . 例如:用户单击按钮,或按键盘上的键 ― 但也有其它类型的事件.例如,如果使用 ActionScri ...

  6. addeventlistener事件第三个参数 passive_JS DOM 事件流、事件冒泡

    当一个HTML元素触发一个事件时,该事件会在元素结点与根结点之间的路径传播.传播按顺序分为三个阶段:捕获阶段.目标阶段.冒泡阶段,这个传播过程就是 DOM 事件流. 事件冒泡就是当一个HTML元素出发 ...

  7. 监听 html dom 变化,如何监听页面 DOM 变动并高效响应

    比来在做 chrome 插件开辟,既然是插件那就不免纰谬现有页面做一些控制,比如事宜监听.调剂构造.对 DOM 元素的增删改查等等.个中有一个需求比较有意思,便整顿一基层便把涉及到的常识点复习一遍. ...

  8. click事件在什么时候出发_超全的js事件机制amp;事件委托

    超全的js事件机制&事件委托,想要理解js事件只需认真看完此篇即可~ 目录结构: 什么是事件机制 事件冒泡事件捕获 DOM事件流事件委托 误区 在同一个对象上注册事件,并不一定按照注册顺序执行 ...

  9. JavaScript 详说事件机制之冒泡、捕获、传播、委托

    DOM事件流(event  flow )存在三个阶段:事件捕获阶段.处于目标阶段.事件冒泡阶段. 事件捕获(event  capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会 ...

最新文章

  1. SpringBoot介绍
  2. 案例_文件下载_代码实现
  3. python错误代码提示手册_腾讯大佬整理了 Python 所有内置异常,Python高手必备的排错手册...
  4. OPPO Reno 2正式发布:主打4800万变焦四摄 售价2999元
  5. python中从键盘输入的代码_python如何从键盘获取输入实例
  6. Python sorted()函数
  7. pycharm python InvalidVersionSpecError: Invalid version spec: =2.7
  8. 计算机硬盘扇区修复,w7硬盘坏道修复详细教程
  9. 车市冷车道 这6款紧凑车苦坐板凳寻伯乐(一)
  10. VUE 对@click的认识
  11. Linux 短链timeout状态,Linux命令——timeout
  12. Python网络编程(OSI Socket)
  13. moviepy音视频开发:音频合成类AudioArrayClip介绍
  14. trinity的简介、下载及使用
  15. 西瓜大作战java 源码_魔改和上线你的合成大西瓜,最全教程!
  16. PS快捷键大法,初级低配版
  17. PS Cloud:最适合中小企业的开源云ERP软件
  18. 温度控制电流c语言编程,利用ATmega16L设计的温度控制系统
  19. TCP状态转换、半关闭、端口复用
  20. java是否会员_java20(判断是否为会员)

热门文章

  1. 区块链以信用为基础,所以目前在中国不可行.
  2. ASP.NET Core 2.0 MVC 发布部署--------- ASP.NET Core 发布的具体操作
  3. Spring环境的搭建与测试 (spring2.5.6)
  4. UVAlive 6131 dp+斜率优化
  5. [源码学习]调试Razor从哪里开始
  6. 根本不存在 DIV + CSS 布局这回事
  7. HDOJ 1030 Delta-wave
  8. MyEclipse6.0 安装axis2插件, 调用加密的SAP webservice
  9. 数据分析工具篇——HQL原理及函数逻辑
  10. 收藏:深度剖析产品经理的「核心竞争力」