事件冒泡和事件捕获的区别

141 阅读2分钟

一、事件冒泡和事件捕获

让我们先从一个例子开始:

<div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
</div>

我们在p元素和div元素都添加点击事件的处理程序,然后点击p元素,会发现上div的处理程序也会运行。

事件冒泡

原理:当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。事件从目标元素“冒泡”到所有父级元素,这个过程就像水里的气泡一样。

p -> div -> body -> html ->document

事件捕获

与事件冒泡相反,事件从最外层的元素发生,直到目标元素。

document ->html -> body -> div -> p

事件冒泡和事件捕获的过程图:

1670465004189.png

先捕获后冒泡。1-5是捕获过程,5-6是目标阶段,6-10是冒泡过程。

二、addEventListener 的第三个参数

addEventListener方法用来为一个特定的元素绑定一个时间处理函数,是JavaScript中常用的方法。

该方法的第三个参数指定事件是否在捕获或冒泡阶段执行。

elem.addEventListener(...,{capture: true})
// 或者,用{capture: true} 的别名 “true”
elem.addEventListener(...,true)

capture选项有两个可能的值:

  • 如果为 false (默认值),则在冒泡阶段设置处理程序。
  • 如果true,则在捕获阶段设置处理程序。

event.target

父元素上的处理程序始终可以获取事件实际发生位置的详细信息。

通过event.target可以访问到目标元素。

注意与this (= event.currentTarget ) 之间的区别:

  • event.target —— 是引发事件的"目标"元素,它在冒泡过程中不会发生变化。
  • this —— 是“当前”元素,其中有一个当前正在运行的处理程序。

阻止事件冒泡

1. 给子级加event.stopPropagation()

elem.addEventListener('click',(event)=>{
    event.stopPropagation();
})

2. 在事件处理函数中返回false

elem.addEventListener('click',(event)=>{
    const e = event || window.event;
    return false;
})

但是这两种方式是有区别的。return false 不仅阻止了事件往上冒泡,而且阻止了事件本身(默认事件)。event.stopPropagation()则只阻止事件往上冒泡,不阻止事件本身。

三、有什么作用

  1. 事件冒泡允许多个操作被集中处理(把事件处理器添加到一个父级元素上,避免把事件处理器添加到多个子级元素上),它还可以让你在对象层的不同级别捕获事件。
  2. 让不同的对象同时捕获同一事件,并调用自己的专属处理程序做自己的事情,就像老板一下命令,各自员工做自己岗位上的工作去了。