DOM事件的传播机制

DOM事件的传播机制是指当一个事件在DOM树中触发时,它是如何在各个元素之间传播的。DOM事件传播机制分为三个阶段:捕获阶段、目标阶段和冒泡阶段。此外,还有一种常用的技术称为事件委托,它能够简化事件处理程序的绑定和管理。本文将详细介绍这些概念,并提供相应的代码示例。

事件与事件流

在介绍事件传播机制之前,我们先来了解一下什么是事件和事件流。在DOM中,事件是指用户与页面交互时发生的动作,比如点击、鼠标移动等。而事件流则是指这些事件在DOM树中传播的路径。

每次用户与一个网页进行交互,例如点击链接,按下一个按键或者移动鼠标时,就会触发一个事件。我们的程序可以检测这些事件,然后对此作出响应。从而形成一种交互。

这样可以使我们的页面变得更加的有意思,而不仅仅像以前一样只能进行浏览。

JavaScript 中采用一个叫做事件监听器的东西来监听事件是否发生。这个事件监听器类似于一个通知,当事件发生时,事件监听器会让我们知道,然后程序就可以做出相应的响应。

通过这种方式,就可以避免让程序不断地去检查事件是否发生,让程序在等待事件发生的同时,可以继续做其他的任务。

标准 DOM 事件流

DOM事件流是指在DOM树中,事件从最外层的节点开始传播,逐级向下,直到达到目标节点,然后再从目标节点向上传播到最外层的节点。

DOM事件流分为三个阶段:捕获阶段、目标阶段和冒泡阶段。

  1. 捕获阶段:事件从最外层的节点开始传播,逐级向下,直到达到目标节点。在捕获阶段中,事件会依次触发每个经过的节点上绑定的捕获型事件处理函数。
  2. 目标阶段:事件达到目标节点后,在目标节点上触发绑定的事件处理函数。在这个阶段中,只会触发目标节点上绑定的事件处理函数。
  3. 冒泡阶段:事件从目标节点开始向上传播,逐级向上,直到达到最外层的节点。在冒泡阶段中,事件会依次触发每个经过的节点上绑定的冒泡型事件处理函数。

在实际应用中,默认情况下大部分DOM事件都是按照冒泡方式进行传播。但是也可以通过调用addEventListener方法时传入第三个参数为true来将其设置为捕获方式进行传播。

总结起来,DOM事件流就是指从最外层的节点开始传播,逐级向下到达目标节点,然后再从目标节点向上传播到最外层的节点的过程。这个过程分为捕获阶段、目标阶段和冒泡阶段。

下面是一个示例,演示了标准 DOM 事件流的传播顺序:

复制代码
html 复制代码
<div id="outer">
  <div id="inner">
    <button id="btn">点击我</button>
  </div>
</div>
复制代码
javascript 复制代码
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');

outer.addEventListener('click', function() {
  console.log('外层元素被点击');
}, true);

inner.addEventListener('click', function() {
  console.log('内层元素被点击');
}, true);

btn.addEventListener('click', function() {
  console.log('按钮被点击');
});

当我们点击按钮时,控制台会输出以下内容:

外层元素被点击 内层元素被点击 按钮被点击

可以看到,事件首先在捕获阶段从外层元素开始传播,然后到达目标元素,最后在冒泡阶段从目标元素向上冒泡。

事件冒泡流

事件冒泡是指在DOM树中,事件从目标元素开始向上冒泡传播的过程。也就是说,在冒泡阶段,事件会依次触发父级元素的相同类型事件处理程序。

下面是一个示例,演示了事件冒泡的过程:

复制代码
html 复制代码
<div id="outer">
  <div id="inner">
    <button id="btn">点击我</button>
  </div>
</div>
javascript 复制代码
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');

outer.addEventListener('click', function() {
  console.log('外层元素被点击');
});

inner.addEventListener('click', function() {
  console.log('内层元素被点击');
});

btn.addEventListener('click', function() {
  console.log('按钮被点击');
});

当我们点击按钮时,控制台会输出以下内容:

按钮被点击 内层元素被点击 外层元素被点击

可以看到,事件首先在目标元素上触发,然后在冒泡阶段依次触发父级元素的相同类型事件处理程序。

事件捕获流

事件捕获是指在DOM树中,事件从最外层的父级元素开始向下捕获传播的过程。也就是说,在捕获阶段,事件会依次触发父级元素的相同类型事件处理程序。

下面是一个示例,演示了事件捕获的过程:

复制代码
html 复制代码
<div id="outer">
  <div id="inner">
    <button id="btn">点击我</button>
  </div>
</div>
javascript 复制代码
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
const btn = document.getElementById('btn');

outer.addEventListener('click', function() {
  console.log('外层元素被点击');
}, true);

inner.addEventListener('click', function() {
  console.log('内层元素被点击');
}, true);

btn.addEventListener('click', function() {
  console.log('按钮被点击');
});

当我们点击按钮时,控制台会输出以下内容:

外层元素被点击 内层元素被点击 按钮被点击

可以看到,事件首先在捕获阶段依次触发父级元素的相同类型事件处理程序,然后到达目标元素。

事件委托流

事件委托是一种常用的技术,它利用了事件冒泡的特性。通过在父级元素上绑定一个事件处理程序,可以监听子级元素触发的事件。这样一来,无论子级元素是已经存在的还是动态生成的,都可以通过父级元素来管理它们的事件。

下面是一个示例,演示了事件委托的过程:

复制代码
html 复制代码
<ul id="list">
  <li>列表项1</li>
  <li>列表项2</li>
  <li>列表项3</li>
</ul>
复制代码
javascript 复制代码
const list = document.getElementById('list');

list.addEventListener('click', function(event) {
  if (event.target.tagName === 'LI') {
    console.log('列表项被点击');
    console.log('触发事件的目标元素是:', event.target);
  }
});

当我们点击任意一个列表项时,控制台会输出以下内容:

列表项被点击 触发事件的目标元素是: <li>列表项1</li>

可以看到,通过在父级元素上绑定点击事件处理程序,我们可以捕获到子级元素触发的点击事件,并且可以获取到触发事件的目标元素。这样一来,无论我们添加或删除列表项,只需要在父级元素上绑定一个事件处理程序即可。

总结

通过以上介绍,我们了解了DOM事件传播机制的三个阶段:捕获阶段、目标阶段和冒泡阶段。此外,我们还学习了如何利用事件委托来简化事件处理程序的绑定和管理。掌握这些概念和技巧,能够帮助我们更好地处理和管理DOM中的各种交互事件。

相关推荐
天涯学馆1 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF1 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi1 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi2 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript
积水成江2 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
Z3r4y2 小时前
【Web】portswigger 服务端原型污染 labs 全解
javascript·web安全·nodejs·原型链污染·wp·portswigger
人生の三重奏2 小时前
前端——js补充
开发语言·前端·javascript
Tandy12356_2 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
老华带你飞2 小时前
公寓管理系统|SprinBoot+vue夕阳红公寓管理系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·spring boot·课程设计
qbbmnnnnnn3 小时前
【WebGis开发 - Cesium】如何确保Cesium场景加载完毕
前端·javascript·vue.js·gis·cesium·webgis·三维可视化开发