tangyuxian
文章79
标签37
分类5
浏览器-事件流理解总结

浏览器-事件流理解总结

关于事件流机制的理解以及对e.target 和 e.currentTarget问题处理

一 DOM事件流

DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。

上面这句话来自百度百科:DOM事件流,该如何理解这句话呢,如图所示,

img

当有事件触发时,从DOM的根节点开始,向内传递,这一过程可以理解成①②③④捕获阶段;如果图中的d节点被触发,事件整个传递到达目标阶段,该阶段结束后,事件会向上传递,这一过程按照水底的气泡一样向上漂,称之为的⑤⑥⑦⑧ 冒泡阶段

结合图和上面的描述可以总结为

在DOM兼容浏览器中,事件流分为3个阶段:

  1. 捕获阶段:事件从Document节点自上而下向目标节点传播的阶段;
  2. 目标阶段:真正的目标节点正在处理事件的阶段;
  3. 冒泡阶段:事件从目标节点自下而上向Document节点传播的阶段

二 捕获事件流

捕获事件流可以在支持W3C 标准的浏览器中使用addEventListener处理,在菜鸟教程:addEventListener 中在线体验.

该函数有三个参数:

  1. 事件名
  2. 触发执行函数
  3. 冒泡阶段还是捕获阶段执行,默认是在冒泡阶段执行

为了理解这个问题,我在网上看到一道十分有意思的题 事件流经典问题:e.target 和 e.currentTarget 有什么区别? ,一起来看下,加深理解.

    <div id="a">
      <div id="b">
        <div id="c">
          <div id="d">点击这里</div>
        </div>
      </div>
    </div>
const a = document.getElementById('a')
const b = document.getElementById('b')
const c = document.getElementById('c')
const d = document.getElementById('d')
a.addEventListener('click', (e) => {
  const {
    target,
    currentTarget
  } = e
  console.log(`target是${target.id}`)
  console.log(`currentTarget是${currentTarget.id}`)
})
b.addEventListener('click', (e) => {
  const {
    target,
    currentTarget
  } = e
  console.log(`target是${target.id}`)
  console.log(`currentTarget是${currentTarget.id}`)
})
c.addEventListener('click', (e) => {
  const {
    target,
    currentTarget
  } = e
  console.log(`target是${target.id}`)
  console.log(`currentTarget是${currentTarget.id}`)
})
d.addEventListener('click', (e) => {
  const {
    target,
    currentTarget
  } = e
  console.log(`target是${target.id}`)
  console.log(`currentTarget是${currentTarget.id}`)
})

想想输出的结果是什么?

addEventListener第三个参数不设置默认是冒泡顺序,当触发d时,呈现的结果如下

target是d currentTarget是d
target是d currentTarget是c
target是d currentTarget是b
target是d currentTarget是a

addEventListener第三个参数设置为true,看看捕获阶段呢?

target是d currentTarget是a
target是d currentTarget是b
target是d currentTarget是c
target是d currentTarget是d

总结如下:

  1. e.target触发事件的元素
  2. e.currentTarget绑定事件的元素

三 事件委托

通过上面的例子,我们可以很清晰的发现,如果当前父级元素下有若干个子级元素,对父级做监听后,当我们通过addEventListener回调函数返回的e.tartget便能得到触发事件的元素.

    <div id='list'>
        <div id='item-1'>item-1</div>
        <div id='item-2'>item-2</div>
        <div id='item-3'>item-3</div>
        <div id='item-4'>item-4</div>
    </div>

通过给id为list的元素添加监听,在点击列表中的元素,便可实现事件委托,事件委托便是处理事件处理程序过多问题的一种解决方案

四 阻止事件流

阻止事件流常用的两种种方式

e.stopPropagation():阻止目标元素的事件冒泡到父级元素;

e.preventDefault():取消一个目标元素的默认行为(例如:a链接,input标签的submit等)

本文作者:tangyuxian
本文链接:https://www.tangyuxian.com/2022/05/06/%E5%89%8D%E7%AB%AF/%E6%B5%8F%E8%A7%88%E5%99%A8/%E6%B5%8F%E8%A7%88%E5%99%A8-%E4%BA%8B%E4%BB%B6%E6%B5%81%E7%90%86%E8%A7%A3%E6%80%BB%E7%BB%93/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可