理解DOM事件流的三个阶段

2023-11-10

本文主要解决两个问题:

  1. 什么是事件流

  2. DOM事件流的三个阶段

起因

在学习前端的大半年来,对DOM事件了解甚少。一般也只是用用onclick来绑定个点击事件。在寒假深入学习JavaScript时,愈发觉得自己对DOM事件了解不够,遂打开我的《JavaScript高级程序设计》,翻到DOM事件那一章,开始第二次学习之旅。
当然,DOM事件所囊括的知识较为庞杂,所以本文专注与自己学习时所碰到的难点,DOM事件流。

流的概念,在现今的JavaScript中随处可见。比如说React中的单向数据流,Node中的流,又或是今天本文所讲的DOM事件流。都是流的一种生动体现。
至于流的具体概念,我们采用下文的解释:

用术语说流是对输入输出设备的抽象。以程序的角度说,流是具有方向的数据。
通通连起来——无处不在的流 淘宝FED--愈之

事件流之事件冒泡与事件捕获

在浏览器发展的过程中,开发团队遇到了一个问题。那就是页面中的哪一部分拥有特定的事件?
可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上所有的圆。放到实际页面中就是,你点击一个按钮,事实上你还同时点击了按钮所有的父元素。
开发团队的问题就在于,当点击按钮时,是按钮最外层的父元素先收到事件并执行,还是具体元素先收到事件并执行?所以这儿引入了事件流的概念。

事件流所描述的就是从页面中接受事件的顺序。

因为有两种观点,所以事件流也有两种,分别是事件冒泡和事件捕获。现行的主流是事件冒泡。

事件冒泡

事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。
举个栗子,就很容易明白了。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Event Bubbling</title>
</head>
<body>
  <button id="clickMe">Click Me</button>
</body>
</html>

然后,我们给button和它的父元素,加入点击事件。

var button = document.getElementById('clickMe');

button.onclick = function() {
  console.log('1. You click Button');
};
document.body.onclick = function() {
  console.log('2. You click body');
};
document.onclick = function() {
  console.log('3. You click document');
};
window.onclick = function() {
  console.log('4. You click window');
};

效果如图所示:

在代码所示的页面中,如果点击了button,那么这个点击事件会按如下的顺序传播(Chrome浏览器):

  1. button

  2. body

  3. document

  4. window

也就是说,click事件首先在<button>元素上发生,然后逐级向上传播。这就是事件冒泡。

事件捕获

事件捕获的概念,与事件冒泡正好相反。它认为当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件。比如说刚才的demo,如果是事件捕获的话,事件发生顺序会是这样的:

  1. window

  2. document

  3. body

  4. button


当然,由于时代更迭,事件冒泡方式更胜一筹。所以放心的使用事件冒泡,有特殊需要再使用事件捕获即可。

DOM事件流

DOM事件流包括三个阶段。

  1. 事件捕获阶段

  2. 处于目标阶段

  3. 事件冒泡阶段

如图所示(图片源于网络,若侵权请告知):

1. 事件捕获阶段

也就是说,当事件发生时,首先发生的是事件捕获,为父元素截获事件提供了机会。
例如,我把上面的Demo中,window点击事件更改为使用事件捕获模式。(addEventListener最后一个参数,为true则代表使用事件捕获模式,false则表示使用事件冒泡模式。不理解的可以去学习一下addEventListener函数的使用)

window.addEventListener('click', function() {
  console.log('4. You click window');
}, true);

此时,点击button的效果是这样的。

可以看到,点击事件先被父元素截获了,且该函数只在事件捕获阶段起作用。

处于目标与事件冒泡阶段

事件到了具体元素时,在具体元素上发生,并且被看成冒泡阶段的一部分。
随后,冒泡阶段发生,事件开始冒泡。

阻止事件冒泡

事件冒泡过程,是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。
这个方法就是:stopPropagation()
我们对button的click事件做一些改造。

button.addEventListener('click', function(event) {
  // event为事件对象
  console.log('1. You click Button');
  event.stopPropagation();
  console.log('Stop Propagation!');
}, false);

点击后,效果如下图:

不难看出,事件在到达具体元素后,停止了冒泡。但不影响父元素的事件捕获。

总结与感想

事件流:描述的就是从页面中接受事件的顺序。分有事件冒泡与事件捕获两种。
DOM事件流的三个阶段:

  1. 事件捕获阶段

  2. 处于目标阶段

  3. 事件冒泡阶段

在学习DOM事件的过程中,了解了DOM事件的三个阶段,也知道事件冒泡是干啥用的,又如何阻止。配合前期所学的二叉树的相关知识,受益匪浅。
转自:https://segmentfault.com/a/1190000004463384

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

理解DOM事件流的三个阶段 的相关文章

  • C语言解释器的实现--序(零)

    在写CuteC文本编辑器的同时 为了使之有脚本执行能力 特意实现了一个简易的C语言解释器 所谓的解释器 就是它是解析执行脚本文件的 并不产生可执行的目标代码 它具备了C语言的几乎全部的语法 随着时间的推移 我打算把它作为一个独立的项目来开发
  • 基于BGP/MPLS 虚拟专用网络实现企业与公网服务的相互访问

    一 实验拓扑图 1 拓扑图 二 实验目的 1 基于BGP MPLS 虚拟专用网络实现企业与公网服务的相互访问 三 设计需求 1 公司总部和分部与 Internet 之间利用 BGP MPLS 虚拟专用网络 实现互通 2 分部之间的通信需通过

随机推荐

  • 栈实现计算机复杂计算

    package com yg stack author GeQiLin date 2020 2 22 14 14 import jdk nashorn internal ir ReturnNode public class Calculat
  • html+向ul追加li内容,肿么用js在ul标签下添加li标签,并要求li有id?

    用 ul append li id tb num class normaltab 新建类型 li 就可以实现 具体添加 参考方法如下 var dy div parent document getElementById xs 这个div在if
  • idea中使用vue.js的前期准备 保姆级教学

    idea的下载安装教程参考 1条消息 IDEA 下载安装教程 桑稚远方 的博客 CSDN博客https blog csdn net weixin 59367964 article details 127900057 安装完之后就可以开始我们
  • 流程图控件GoJS内置GraphObject类各指数介绍

    GoJS是一款功能强大 快速且轻量级的流程图控件 可帮助你在JavaScript 和HTML5 Canvas程序中创建流程图 且极大地简化您的JavaScript Canvas 程序 点击下载GoJS最新版 背景点击 功能 InputEve
  • 动态规划学习(一)

    动态规划算法与分治法类似 其基本思想也是将待求解问题分解成若干个子问题 但是经过分解得到的子问题往往不是相互独立的 在用分治法求解的时候 子问题被重复计算了多次 解决方法 保存已解决的子问题的答案 避免大量重复计算 动态规划与分治法区别 适
  • 前端学习:表格学习,附练习+源码

    文章目录 一 表格的主要作用 二 表格属性 三 总结 四 合并单元格方式 一 表格的主要作用 1 表格主要用于显示 展示数据 因为它可以让数据显示的非常的规整 可读性非常好 特别是后台展示数据的时候 能够熟练运用表格就显得很重要 一个清爽简
  • 微信公众号群发接口和原创校验

    一 说明 1 1限制 二 群发图文消息 三 群发图片 文本 四 群发时使用is to all 五 上传图文消息接口 5 1 上传图文消息内的图片获取URL 订阅号与服务号认证后均可用 5 2 上传图文消息素材 订阅号与服务号认证后均可用 六
  • C语言变长数组讲解

    C语言变长数组讲解 参考资料 1 https www cnblogs com Anker p 3744127 html 2 https www cnblogs com veis p 7073076 html 3 https blog csd
  • EXCEL解析导入,多线程批量插入大量数据

    EXCEL解析导入 批量插入大量数据 excel导入基本分为3个步骤 1 上传文件 2 解析文件 3 逻辑内容 首先查看是哪一步需要优化 一般需要在第3步 插入数据库的逻辑优化 如果数据量比较大的话 单条sql执行很慢 几条数据几次和数据库
  • Alibaba Java Code Guidelines

    Alibaba Java Code Guidelines这个代码规范插件 对于Java代码规范 业界有统一的标准 不少公司对此都有一定的要求 但是即便如此 庞大的Java使用者由于经验很水平的限制 未必有规范编码的意识 而且即便经验丰富的老
  • 提取python字符串括号中的内容

    一些数据按字符串保存 如str1 1 0 123 2 0 234 当我们需要将字符串中的数据提取出来进行计算时 涉及只提出括号中的内容 此时可采取用Python re正则表达式模块和split 函数完成 操作过程略复杂 有更简洁方法时再更新
  • 每日一题(C语言基础篇)3

    题目描述 求一个整数中2进制为1的个数 例如 8 00001000 有一个二进制为1的数 9999 270F 有8个2进制为1的数 代码实现 include
  • 树莓派4B串口配置

    树莓派环境 硬件 树莓派4B 系统 ubuntu22 04 串口信息 树莓派4B一共有6个串口 之前的版本只有2个串口 这6个串口中 有5个时硬件串口 还有个mini串口 这5个硬件串口在我们需要使用外设时 但是 默认情况下 5个默认串口只
  • Qt与VS的对比(1)

    对话框篇 QT与VS创建对话框的方式非常相似 都需要创建一个对话框类 在需要显示该对话框的地方包含对应的头文件 显示即可 区别 QT显示模态对话框使用函数QDialog exec VS显示模态对话框使用函数CDialog DoModal Q
  • JDK的下载与安装详细解释

    JDK的下载与安装 一 JDK下载 进入Oracle官网 https www oracle com index html 打开后我们通过选项卡找到Downloads 操作如下界面 接下来我们找到Deverloper Downloads中的J
  • Unity3D之简单的点击拾取

    新建一个Cube物体和一个脚本Cube 将Cube脚本挂到Cube物体上 代码如下 csharp view plain copy using UnityEngine using System Collections public class
  • Web Components 系列(八)—— 自定义组件的样式设置

    前言 通过前面的学习 对自定义组件的相关概念和知识点也有了一定了解 今天我们就来学习一下给自定义元素及其子元素设置样式的几种方法 直接给自定义标签添加样式 index html
  • 多module启动报错Could not resolve dependencies for project

    前几天用若依的前后端分离版本 项目能启动 打包发布时异常 提示找不到项目依赖 无法解析artifact Could not resolve dependencies for project The following artifacts c
  • [管理与领导-82]:IT基层管理者 - 核心技能 - 高效执行力 - 7- 高效执行的结果通过高效的过程保证

    目录 前言 一 执行前 对 1 1 确保做对事 do right thing 1 目标 行动的目标 2 方向 行动的方向 3 需求 行动是为了满足某种需求 4 指令 行到受谁的指令 1 2 确定做对事的方法 1 2 1 确认 do righ
  • 理解DOM事件流的三个阶段

    本文主要解决两个问题 什么是事件流 DOM事件流的三个阶段 起因 在学习前端的大半年来 对DOM事件了解甚少 一般也只是用用onclick来绑定个点击事件 在寒假深入学习JavaScript时 愈发觉得自己对DOM事件了解不够 遂打开我的