美文网首页
dom 事件流机制

dom 事件流机制

作者: 菜鸡前端 | 来源:发表于2021-08-28 14:59 被阅读0次

1. dom 事件流

DOM结构是一个树型结构,当一个 HTML元素 产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。

当触发事件时,该事件的捕获阶段最先开始,从 Document 节点开始逐渐向下传播,直到触发源事件进入目标阶段,在目标阶段结束之后,事件由触发源开始事件的冒泡阶段,直到 Document 节点为止,即3个阶段:

  • 捕获阶段
  • 目标阶段
  • 冒泡阶段
image.png

2. 冒泡与捕获演示

使用 addEventListener 注册事件

event 指定事件名,不要使用 "on" 前缀,可以完整的 HTML DOM Event 对象参考手册
function 必须,指定要事件触发时执行的函数,当事件对象会作为第一个参数传入函数
useCapture |object 可选。布尔值或对象,指定事件是否在捕获或冒泡阶段执行,可能值: true - 事件句柄在捕获阶段执行;false- 默认。事件句柄在冒泡阶段执行

分三种场景做演示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>冒泡与捕获</title>
  <style>
    #b1 {
      width: 100px;
    }
    div {
      padding: 20px;
      border: 1px solid red;
    }
  </style>
</head>
<body>
    <div id="b1">
      <div id="b2">
        <div id="b3"></div>
      </div>
    </div>
</body>
<script>
  var b1 = document.querySelector("#b1");
  var b2 = document.querySelector("#b2");
  var b3 = document.querySelector("#b3");

  // 1. 全是冒泡阶段执行,谁的层级深,谁的回调先执行  => b3 b2 b1
  // b1.addEventListener('click', function() {
  //   console.log("b1 click")
  // })
  // b2.addEventListener('click', function() {
  //   console.log("b2 click")
  // })
  // b3.addEventListener('click', function() {
  //   console.log("b3 click")
  // })

  // 2. 全是捕获阶段执行,谁的层级低,谁的回调先执行 => b1 b2 b3
  // b1.addEventListener('click', function() {
  //   console.log("b1 click")
  // }, true)
  // b2.addEventListener('click', function() {
  //   console.log("b2 click")
  // }, true)
  // b3.addEventListener('click', function() {
  //   console.log("b3 click")
  // }, true)

  // 3. 混合,先执行捕获, 再冒泡 => b2 b3 b1
  b1.addEventListener('click', function() {
    console.log("b1 click")
  })
  b2.addEventListener('click', function() {
    console.log("b2 click")
  }, true)
  b3.addEventListener('click', function() {
    console.log("b3 click")
  })
</script>
</html>

3. 阻止事件的传播

如下代码分别演示了,在冒泡阶段阻止事件传播,以及在捕获阶段阻止事件传播:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #b1 {
      width: 100px;
    }
    div {
      padding: 20px;
      border: 1px solid red;
    }
  </style>
</head>
<body>
    <div id="b1">
      <div id="b2">
        <div id="b3"></div>
      </div>
    </div>
</body>
<script>
  var b1 = document.querySelector("#b1");
  var b2 = document.querySelector("#b2");
  var b3 = document.querySelector("#b3");

  // 1. => b3 b2
  // b1.addEventListener('click', function() {
  //   console.log("b1 click")
  // })
  // b2.addEventListener('click', function(e) {
  //   console.log("b2 click")
  //   e.stopPropagation(); // b1 冒泡回调不会执行
  // })
  // b3.addEventListener('click', function() {
  //   console.log("b3 click")
  // })

  // 2.  => b1 true click
  b1.addEventListener('click', function(e) {
    console.log("b1 true click")
    e.stopPropagation(); // 由于是在捕获阶段就阻止了事件传播,所以其子元素都不会触发事件
  }, true)
  b1.addEventListener('click', function(e) {
    console.log("b1 false click")
  }, false)
  b2.addEventListener('click', function() {
    console.log("b2 click")
  }, true)
  b2.addEventListener('click', function() {
    console.log("b2 false click")
  }, false)
  b3.addEventListener('click', function() {
    console.log("b3 click")
  }, true)
</script>
</html>

4. 参考文档

相关文章

网友评论

      本文标题:dom 事件流机制

      本文链接:https://www.haomeiwen.com/subject/kcvbiltx.html