Spirit带你彻底了解事件捕获和冒泡机制

Dom标准事件模型

在Dom标准事件模型中,事件是先进行捕获,达到目标阶段时,在进行冒泡的

捕获阶段==>目标阶段==>冒泡阶段

image-20210914235653177

目标元素和非目标元素

在介绍事件捕获和事件冒泡前

我们先要了解一下目标元素和非目标元素是什么意思

  • 目标元素:它是我们当前触发事件的元素
  • 非目标元素:它是在捕获阶段或着冒泡阶段中因为绑定了同类型的事件而触发的元素
  • 每个Dom元素可以绑定多个事件,前提是使用addEvenetListener去添加事件,即使是相同的事件,也可以重复绑定.

事件捕获

从页面的根元素开始 一层一层的往下寻找

可以看下我在最上面画的那张图

事件冒泡

从目标元素一直往上寻找

可以看下我在最上面的那张图

addEventListener

addEventListener可以传入第三个参数useCapture,默认是false

其实还有一个option参数可以传递,但是我没细看,因为目前我看了,我也不知道应用场景,所以打算有需求了,后面在看

  • useCapture参数会false时,默认是捕获阶段 不会触发事件监听,会在冒泡阶段触发事件监听
  • useCapture参数会true时,事件监听时从捕获阶段开始,但是冒泡阶段不会触发事件监听

举例说明

现在我们来分析一道题, 布局代码都在下面了

HTML代码

<!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>
</head>
<style>
    .c {
        width: 200px;
        height: 200px;
        background-color: orange;
    }
</style>

<body>
    <div class="a">
        a
        <div class="b">
            b
            <div class="c">c</div>
        </div>
    </div>
</body>
    
<script src="./script.js"></script>
</html>

JS代码

const a = document.querySelector(".a");
const b = document.querySelector(".b");
const c = document.querySelector(".c");




a.addEventListener("mousedown", () => {
    alert("弹出a");
}, false)
b.addEventListener("mousedown", (e) => {
    alert("弹出b");
}, true)

c.addEventListener("mousedown", (e) => {
    console.log(e)
    alert("mousedown2");
}, true)
c.addEventListener("mousedown", (e) => {
    alert("mousedown1");
}, false)
c.addEventListener("mousedown", (e) => {
    console.log(e)
    alert("mousedown3");
}, false)
c.addEventListener("mousedown", (e) => {
    console.log(e)
    alert("mousedown4");
}, true)

分析

  1. 从HTML来看,嵌套层级是 a>b>c

  2. 现在来看JS代码

  3. a,b,c都绑定了mousedown事件,我们仔细看下,这个的执行顺序是怎么样的?

  4. 我可以在给你们分析一下

  5. 对于同一个元素,绑定多个事件,无论是一样的事件,还是不一样的事件,只要是触发了对应事件的监听器,那么它都会执行

  6. 那么同一个事件的执行顺序是怎么样的呢?

  7. 同一个事件的执行顺序是根据定义的顺序来执行的,前提是useCapture保持一致

  8. 当我们点击目标元素时,我们是处于目标阶段的,而不是处于冒泡阶段或者捕获阶段,这一句话请牢牢记住

  9. 处于目标阶段时,当useCapture有true,又有false的阶段时
    这个时候 我们可以理解为目标元素其实是形成了一个类似于Dom事件模型的东西.
    在这个模型内,也有捕获阶段和冒泡阶段.
    所以如果有true的话,会先执行捕获阶段,按照定义顺序
    然后执行fasle阶段,也就是冒泡阶段,按照事件的定义顺序

  10. 所以在目标阶段执行的时候,这么多事件的执行顺序就是 mousedown2 mousedown4 mousedown1 mousedown3

  11. 那么我们现在可以看下这个整个HTML页面,这个执行顺序是什么样的呢?

  12. 其实和目标阶段的执行是一样的
    非目标元素的useCapture为true时,捕获阶段会先执行事件监听
    非目标元素的useCapture为false时,会在捕获阶段和目标阶段执行完毕后,在冒泡阶段执行事件监听
    举个例子,如果我在b身上也绑定了多个相同类型的事件,在有true,有false的情况下,它会先执行true的,false的不会等true执行完毕后就立马执行,而是等待目标阶段执行完毕后,才继续执行
    大家如果不信的,可以自己去尝试一下

  13. 所以整体的执行顺序是

    b mousedown2 mousedown4 mousedown1 mousedown3 a

图解

我怕大家还是不明白我说的是什么意思
所以我画了这张图,把这个过程给大家详细介绍一下

image-20210915110603594

posted @ 2021-09-18 08:00  CodeSpirit  阅读(409)  评论(0编辑  收藏  举报