[Day20] JavaScript - Event Bubbling (事件冒泡) & Event Capturing (事件捕获)

Event Flow 事件流

DOM的Event flow概念,指的是「网页元素接收事件的顺序」。

假如有两个重叠的<div>,外层是outer内层是inner:
https://ithelp.ithome.com.tw/upload/images/20210920/20141293JdPW301DHG.png

由於inner被包在outer里面,所以当我们点击inner时,也代表我们也点击到了outer;若再将范围扩大,实际上我们也点击了整个网页。

事件冒泡 & 捕获

而上面这样子的事件传播概念即是Event Flow - 事件流,Event Flow可分为以下两种方式:

  • 事件冒泡 (Event Bubbling): 从启动事件的元素节点开始,逐层往外传递,直到整个网页的根节点,也就是 document。
  • 事件捕获 (Event Capturing): 由 DOM 树的最外层(document)依序向内,逐渐往下传递,直到启动事件的元素点。

当 DOM 事件发生时,事件会先由外到内 (capturing phase)、再由内到外 (bubbling phase) 的顺序来传播。

根据 W3C 所定义的 Event Flow:
https://www.w3.org/TR/DOM-Level-3-Events/images/eventflow.svg

如下范例:

<html>
    <head>
        <title>Event flow</title>
    </head>
    <body>
        <div>
            <ul>
                <li></li>
            </ul>
        </div>
    </body>
</html>
  • 当使用者点击 li 元素时,事件触发的顺序是:
    • Capturing 捕捉阶段:document -> <html> -> <body> -> <div> -> <ul> -> <li>
    • Bubbling 冒泡阶段:<li> -> <ul> -> <div> -> <body> -> <html> -> document
  • DOM 中的元素会按照上面的顺序依序地触发其 click 事件。

另外,在 addEventListener 和 removeEventListener 方法中,可以传递第三个参数(布林值),用来指定事件处理函数是要在 Capturing 阶段或 Bubbling 阶段被执行。

如果是false就用事件冒泡(bubbling),如果是true就使用事件捕捉(capturing)。
没写的话,预设就是false,也就是预设使用事件冒泡(bubbling)机制:

element.addEventListener('click', eventHandler) // 未指定,预设为冒泡
element.addEventListener('click', eventHandler, false) // 冒泡
element.addEventListener('click', eventHandler, true) // 捕获

 
 范例

<div id="parent">
  父元素
  <div id="child">子元素</div>
</div>
var parent = document.getElementById("parent");
var child = document.getElementById("child");

parent.addEventListener("click", function() {
  console.log("Parent capturing")
}, true);

parent.addEventListener("click", function() {
  console.log("Parent bubbling")
}, false);

child.addEventListener("click", function() {
  console.log("Child capturing")
}, true);

child.addEventListener("click", function() {
  console.log("Child bubbling")
}, false);
  • 当点击父元素时,console.log的结果为:
    Parent capturing
    Parent bubbling

  • 当点击子元素时,console.log的结果为:
    Parent capturing
    Child capturing
    Child bubbling
    Parent bubbling

以上结果可见,当点击子元素时,会先从外层的父元素开始传递,再到内层子元素,再从子层回到父层。

 
 
 

参考资料:
https://www.fooish.com/javascript/dom/event.html
https://ithelp.ithome.com.tw/articles/10191970


<<:  [前端暴龙机,Vue2.x 进化 Vue3 ] Day11.列表渲染

>>:  Day06:06 - User服务(1) - 後端 - 注册、登入、Python正则表达式

rsync异地备份+排程自动化

今天要接续昨天的排程备份来实作「异地备份」 读者们如果对rsync操作尚不熟悉,可到 昨天 复习喔 ...

Day17:今天来聊一下如何使用macof产生MAC Flooding

MAC Flooding是一种用於危及连接网段或网络设备的网路Switch安全技术。 攻击者使用MA...

Day 16 ( 中级 ) 灯光绕圈圈 ( 座标 )

灯光绕圈圈 ( 座标 ) 教学原文参考:灯光绕圈圈 ( 座标 ) 这篇文章会介绍如何使用「重复无限次...

Day16|什麽是 HEAD ?

在先前的章节里,我们可以常看见 HEAD 这个名词,它指的是什麽呢? // git 恢复文件到初始状...