【Web APIs】JavaScript 事件高级 ③ ( DOM 事件流 | 捕获阶段 | 目标阶段 | 冒泡阶段 )

文章目录

  • [一、DOM 事件流](#一、DOM 事件流)
    • [1、DOM 事件流简介](#1、DOM 事件流简介)
    • [2、捕获阶段 Capture Phase](#2、捕获阶段 Capture Phase)
    • [3、目标阶段 Target Phase](#3、目标阶段 Target Phase)
    • [4、冒泡阶段 Bubbling Phase](#4、冒泡阶段 Bubbling Phase)
    • [5、DOM 事件流案例说明](#5、DOM 事件流案例说明)
  • 二、代码示例
    • [1、捕获阶段 事件处理 代码示例](#1、捕获阶段 事件处理 代码示例)
      • [① 代码示例](#① 代码示例)
      • [② 执行结果](#② 执行结果)
    • [2、冒泡阶段 事件处理 代码示例](#2、冒泡阶段 事件处理 代码示例)
      • [① 代码示例](#① 代码示例)
      • [② 执行结果](#② 执行结果)

一、DOM 事件流


1、DOM 事件流简介

DOM 事件流 描述了 在页面中 发生某个事件 时 , 事件如何 在 DOM 树中的 元素之间 传播的过程 ;

DOM 事件流分为 3 个阶段 :

  • 捕获阶段 ( Capture Phase ) : 事件从 最顶层的父元素 document 开始 , 沿着 DOM 树向下传播到 目标元素 的 父元素 ;
    • 核心作用 : 可以令 上层元素 提前拦截、处理事件 ;
    • 关键特点 : 事件自上而下传播 , 需在 addEventListener 方法中 显式注册 , 第三参数设置 true ;
  • 目标阶段 ( Target Phase ) : 事件到达 并 触发在目标元素本身 ;
    • 核心作用 : 触发 目标元素 自身的 事件处理 ;
    • 关键特点 : 事件的最终目的地 , 按注册顺序执行处理函数 ;
  • 冒泡阶段 ( Bubbling Phase ) : 事件 从目标元素开始 , 沿着 DOM 树向上传播回最顶层的父元素 document ;
    • 核心作用 : 令祖先元素 共享 事件处理机会 ;
    • 关键特点 : 自下而上传播 , 支持事件委托 ;

2、捕获阶段 Capture Phase

捕获阶段 中 事件 从 最顶层的父元素 document 开始 , 沿着 DOM 树向下传播到 目标元素 的 父元素 ;

  • 传播方向 : 顶层 document 元素 -> html 元素 -> body 元素 -> ... -> 父元素 -> 目标元素的父元素 -> 目标元素 ;
  • 阶段目的 : 在事件到达 目标元素 之前 , 给上层元素一个机会来 捕获 和 处理 它 ;
  • 触发操作 : 默认情况下 , 事件处理程序 不会在这个阶段触发 , 你需要通过 特定的方式 来注册捕获阶段的事件处理程序 , 如 : 设置 addEventListener 的 第三个参数 可以在 捕获阶段 触发事件回调函数 ;

3、目标阶段 Target Phase

目标阶段 事件 到达 并 触发 在目标元素本身 ;

  • 传播方向 : 事件 直接作用于 触发事件 的元素 , 如 : 点击的按钮、输入的输入框 ;
  • 核心目的 : 执行 目标元素 上绑定的所有 事件处理程序 , 这是事件的 " 最终目的地 " ;
  • 多阶段注册 : 如果一个元素上 同时注册了 捕获阶段 和 冒泡阶段 的处理程序 , 它们会在这个阶段 按照 注册顺序 依次执行 , 先注册的先执行 ;

4、冒泡阶段 Bubbling Phase

冒泡阶段 Bubbling Phase 中 事件 从目标元素开始 , 沿着 DOM 树向上传播回最顶层的 document 元素 ;

  • 传播方向 : 目标元素 -> 父元素 -> ... -> body 元素 -> html 元素 -> 顶层 document 元素 ;
  • 核心目的 : 让目标元素的所有祖先元素都有机会处理这个事件 , 这是事件委托的核心原理 ;
  • 注意点 : 大多数事件 ( click、input、mouseover ) 都有冒泡阶段 , 少数事件 ( focus、blur、load、unload ) 没有冒泡阶段 ;

5、DOM 事件流案例说明

下面的 DOM 事件流 是 为某个 <div> 标签元素 注册点击事件 并 执行 的过程分析 ;

事件捕获阶段 : 事件 从最顶层的 document 开始 , 自上而下依次传播到 html、body、div 等元素 , 即从祖先元素向目标元素的父元素传播 ;

该阶段让上层元素有机会提前拦截、处理事件 , 比如一些全局的事件控制可以在这个阶段实现 ;

事件目标阶段 : 当 事件传播到 最具体 的 目标元素(图中 "处于目标阶段" 对应的元素,通常是触发事件的具体节点,如这里的 div 所关联的实际元素)时,进入目标阶段 ;

该阶段的作用是 执行目标元素自身的事件处理程序 , 这是事件的 最终作用点 ;

事件冒泡阶段 : 事件 从目标元素开始 , 自下而上 依次 传播回 body、html、document , 即 从目标元素向祖先元素反向传播 ;

该阶段的作用是 让 目标元素 的 所有祖先元素 都有机会处理事件 , 这是事件委托的核心原理 , 只需给父元素绑定事件 , 就能处理子元素的事件 ;

二、代码示例


1、捕获阶段 事件处理 代码示例

① 代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM 事件流</title>
    <style>
        .father {
            /*
                父子元素的 margin 折叠 : 
                    子元素的 margin-top/margin-bottom 可能会 "穿透" 父元素,
                    与父元素的 margin 合并 , 导致子元素的垂直 margin 失效
                该 overflow: hidden 属性 可以阻止内部元素与外部元素的 margin 折叠
             */
            overflow: hidden;
            width: 200px;
            height: 200px;
            margin: 50px auto;
            background-color: green;
        }
        
        .son {
            width: 150px;
            height: 150px;
            margin: 25px;
            background-color: red;
            line-height: 150px;
            color: #fff;
            text-align: center;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son">目标元素</div>
    </div>
    <script>
        // 捕获阶段 事件处理
        // 调用 addEventListener 方法 设置第三个参数是 true
        // 捕获阶段事件传递顺序  document -> html -> body -> father -> son

        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, true);

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, true);

        document.addEventListener('click', function() {
            alert('document');
        }, true)
    </script>
</body>

</html>

② 执行结果

执行后 , 点击子元素 , 捕获阶段 事件触发顺序 : 顶层 document 元素 -> 父元素 -> 子元素 ;

2、冒泡阶段 事件处理 代码示例

① 代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DOM 事件流</title>
    <style>
        .father {
            /*
                父子元素的 margin 折叠 : 
                    子元素的 margin-top/margin-bottom 可能会 "穿透" 父元素,
                    与父元素的 margin 合并 , 导致子元素的垂直 margin 失效
                该 overflow: hidden 属性 可以阻止内部元素与外部元素的 margin 折叠
             */
            overflow: hidden;
            width: 200px;
            height: 200px;
            margin: 50px auto;
            background-color: green;
        }
        
        .son {
            width: 150px;
            height: 150px;
            margin: 25px;
            background-color: red;
            line-height: 150px;
            color: #fff;
            text-align: center;
        }
    </style>
</head>

<body>
    <div class="father">
        <div class="son">目标元素</div>
    </div>
    <script>
        // 冒泡阶段 事件处理
        // 调用 addEventListener 方法 设置第三个参数是 false , 如果不设置默认也是 false
        // 冒泡阶段事件传递顺序  son -> father ->body -> html -> document

        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, false);

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);

        document.addEventListener('click', function() {
            alert('document');
        })
    </script>
</body>

</html>

② 执行结果

执行后 , 点击子元素 , 冒泡阶段 事件触发顺序 : 子元素 -> 父元素 -> 顶层 document 元素 ;

相关推荐
p***h64313 分钟前
React数据分析应用
前端·react.js·前端框架
4***997414 分钟前
TypeScript类型体操
前端·javascript·typescript
u***096415 分钟前
TypeScript装饰器
前端·javascript·typescript
h***839327 分钟前
React虚拟现实开发
前端·react.js·vr
7***n7531 分钟前
React虚拟现实案例
前端·react.js·vr
IT_陈寒1 小时前
JavaScript 闭包通关指南:从作用域链到内存管理的8个核心知识点
前端·人工智能·后端
默恋~微凉1 小时前
shell(八)——WEB与Nginx
开发语言·前端·php
要加油哦~1 小时前
nrm | npm 的镜像管理工具
前端·npm·node.js·nrm
想不明白的过度思考者1 小时前
基于 Spring Boot 的 Web 三大核心交互案例精讲
前端·spring boot·后端·交互·javaee