数字营销 · Web开发 · 基础设施

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

通过简单的 DOM 示例,对比 JavaScript 事件捕获与事件冒泡的传播方向和执行顺序。

事件是 JavaScript 客户端编程中非常常见的内容,常见的事件有 click、mouseover、mouseenter、keyup、focus 等。只要接触过 JavaScript 事件,相信对“事件冒泡”和“事件捕获”这两个概念都或多或少听说过,那么它们到底有什么区别呢?

什么是事件冒泡?

当事件在某一个 DOM 元素上被触发时,例如用户在某个节点上点击鼠标,事件会跟随着这个节点的父节点,逐级向上冒泡,穿过整个 DOM 节点层次。当它遇到绑定了该事件类型处理器的节点时,相应的事件处理函数就会被触发。

事件冒泡
事件冒泡

前一篇文章《HTML中动态生成内容的事件绑定问题》中,我们已经讲到了事件冒泡。简单来说,就是:

子元素发生的事件,会逐级冒泡到父元素。

如果一个或多个父元素上也绑定了相同的事件,那么相应的事件处理函数也会被触发。事件冒泡比较容易理解。我们知道,子元素被父元素包含,当子元素上发生事件,例如点击时,从事件传播的角度来看,父元素也会受到这个事件的影响。来看下面的例子:

<div id="parent"
onclick="alert('Parent')"
style="width:200px;height:200px;border:1px solid #ccc">

<div id="child"
onclick="alert('Child')"
style="width:98px;height:98px;border:1px solid #ccc;margin:50px">

Child

</div>

</div>

当点击 id 为 child 的盒子时,会先弹出:

Child

然后再弹出:

Parent

这是因为点击 child 后,事件继续向父元素 parent 冒泡,所以父元素上的 onclick 也被触发了。

什么是事件捕获?

那么,能不能让 Parent 先弹出来呢?实际上,当时的高级浏览器提供了相应的方法,父元素可以在子元素事件处理函数执行之前,先捕获到这个事件,这就是事件捕获。也就是说:

在子元素的事件处理函数被调用之前,父元素可以先捕获到这个事件并作出处理。

事件捕获
事件捕获

还是使用刚才的例子:

<div id="parent"
style="width:200px;height:200px;border:1px solid #ccc">
<div id="child"
onclick="alert('Child')"
style="width:98px;height:98px;border:1px solid #ccc;margin:50px">
Child
</div>

</div>
<script>

var parent = document.getElementById("parent");
parent.addEventListener(
"click",
function(){
alert("Parent");
},
true
);

</script>

这里:

true

表示使用捕获方式监听事件。当点击 id 为 child 的盒子时,执行结果就是:

Parent
Child

也就是父元素先捕获到事件,然后才执行子元素自己的事件处理函数。

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

简单总结一下:

事件冒泡和事件捕获,实际上定义了具有父子关系的元素在事件传播过程中,事件处理函数的调用先后顺序。

事件冒泡:

从子元素开始,事件逐级向父元素传播。

事件捕获:

从父元素开始,先捕获子元素即将发生的事件,再到达子元素。

所以,两者最直观的区别就是:

事件捕获:父 → 子
事件冒泡:子 → 父

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。