JavaScript的事件捕获你知道吗?

176 阅读3分钟

「这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

虽然事件捕获在实际开发中很少被用到,但是有时是有用的,所以一起来了解一下吧!

前言

首先需要知道的是,一个事件传播它会有3个阶段

  • 捕获阶段(Capturing phase)—— 事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
  • 目标阶段(Target phase)—— 事件到达目标元素。
  • 冒泡阶段(Bubbling phase)—— 事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。

这是一个点击表格<td>的图片(来自👉W3C规范

image-20211127011718773

可以看到,点击<td>时,

  • 事件首先通过祖先链向下到达元素(即红色那路线,Capturing phase【捕获阶段】)
  • 然后到达目标(即到达<td>元素,Target phase【目标阶段】)
  • 最后又从td重新回到顶级(即绿色那条路线,Bubbling phase【冒泡阶段】)

假如有一个元素div,它有一个下级元素p

<div id="div">
    DIV 
    <p id="p"> P </p>
</div>

此时,如果给它们都绑定了click事件,哪个元素的click先触发呢?

image-20211127013839991

如果点击P标签,打印的结果是

image-20211127014652920

说明是p先触发,div后触发,这里发生的就是事件冒泡。

冒泡👉【传送门

如果想要换成事件捕获,也很简单,只需要把addEventListener函数的第三个参数改为true即可。可以试一下

let div = document.getElementById("div")
let p = document.getElementById("p")

function divClick(){  console.log("点击DIV");}
function pClick(){   console.log("点击P标签"); }


div.addEventListener('click', divClick, true);
p.addEventListener('click', pClick, true);

这个时候你在点击P标签,结果是

image-20211127014706404

即div先触发,p后触发,这就是【事件捕获】

👉 addEventListener介绍

总结

  • 冒泡 ,内部元素的事件会先被触发,然后再触发外部元素,即:<p>元素的点击事件先触发,然后会触发 <div> 元素的点击事件。

  • 捕获 ,外部元素的事件会先被触发,然后才会触发内部元素的事件,即: <div> 元素的点击事件先触发 ,然后再触发 <p> 元素的点击事件。

捕获阶段很少使用,通常我们会在冒泡时处理事件。这背后有一个逻辑。

在现实世界中,当事故发生时,当地警方会首先做出反应。他们最了解发生这件事的地方。然后,如果需要,上级主管部门再进行处理。

事件处理程序也是如此。在特定元素上设置处理程序的代码,了解有关该元素最详尽的信息。特定于 <td> 的处理程序可能恰好适合于该 <td>,这个处理程序知道关于该元素的所有信息。所以该处理程序应该首先获得机会。

然后,它的直接父元素也了解相关上下文,但了解的内容会少一些,以此类推,直到处理一般性概念并运行最后一个处理程序的最顶部的元素为止。

参考资料:

Event dispatch and DOM event flow

Bubbling and capturing


🎨【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

👉 一起来看看JS的原型继承

👉 JS中的getter和setter你会用吗?

👉 深入理解ES6箭头对象

👉 JS的装饰器模式实例分析