JS事件冒泡与捕获

99 篇文章 12 订阅
33 篇文章 1 订阅

DOM事件流

  • 事件流所描述的就是从页面中接受事件的顺序。
  • DOM事件流(event flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。
  • 浏览器在为这个当前页面与用户做交互的过程中,比如我点击了这个鼠标左键,这个左键是怎么传到页面上。还有怎么响应的。事件流分三个阶段,第一阶段是捕获,第二阶段是目标阶段,比如点击的这个按钮,这个按钮就是目标阶段,事件通过捕获到达目标元素,就到达了目标阶段,第三个阶段是冒泡阶段,从目标元素再上传到window对象,就是冒泡的过程。

事件传播——冒泡与捕获

  默认情况下,事件使用冒泡事件流,不使用捕获事件流。然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true。

冒泡事件流

 事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。在遵从W3C标准的浏览器里可以通过调用事件对象上的stopPropagation()方法,在Internet Explorer里可以通过设置事件对象的cancelBubble属性为true。如果不停止事件的传播,事件将一直通过DOM冒泡直至到达文档根。

DOM事件冒泡的具体流程:第一个接收的是目标元素——第二个接收的是...(子级--父级,按照html结构一层一层往上传)——然后接收的是body标签——html标签——document对象——最后一个接收的是window对象。

捕获事件流

  事件的处理将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。在这个过程中,事件会被从文档根到事件目标元素之间各个继承派生的元素所捕获,如果事件监听器在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。

DOM事件捕获的具体流程:捕获是从上到下,具体第一个真正接收的是window(对象)——第二个接收的是document(对象)——第三个接收的是html标签(怎么获取html标签>document.documentElement)——第四个接收的是body(document.body)——......(父级--子级,剩下的就是按照普通的html结构一层一层往下传)——最后到达目标元素。

冒泡与捕获详解

以click点击事件为例。假如我们有一个多层结构标签。如下图,是4个div嵌套。每个div都有点击的监听事件,分别输出1234。当我们点击最里面的div时,点击事件开始传递,传递的全过程是1-2-3-4-4-3-2-1
前半部分,事件从最外面的父div依次传递到最里面的后代div,1-2-3-4这部分我们叫捕获过程
之后事件又从最里层的后代div逐层传出,4-3-2-1这部分我们叫冒泡过程

如果我把捕获监听器和冒泡监听器都加上,如下图这样。

<div style="background: red;width: 240px;height: 240px" @click.capture="log(1)" @click="log(1)">
    <div style="background: green;width: 200px;height: 200px" @click.capture="log(2)" @click="log(2)">
        <div style="background: blue;width: 150px;height: 150px" @click.capture="log(3)" @click="log(3)">
            <div style="background: black;width: 100px;height: 100px" @click.capture="log(4)" @click="log(4)">
            </div>
        </div>
    </div>
</div>

methods: {
    log (str) {
        console.log(str)
    },
}

更改代码如下

<div style="background: red;width: 240px;height: 240px" @click="log(1)">
    <div style="background: green;width: 200px;height: 200px" @click.capture="log(2)">
        <div style="background: blue;width: 150px;height: 150px" @click="log(3)">
            <div style="background: black;width: 100px;height: 100px" @click.capture="log(4)">
            </div>
        </div>
    </div>
</div>

将输出:2 4 3 1 

阻止传递

在不使用任何框架的情况下,我们在js中通过stopPropagation方法阻止事件继续传递。 Vue框架使用stop修饰符来阻止事件传递。

<div style="background: red;width: 240px;height: 240px" @click.capture="log(1)" @click="log(1)">
    <div style="background: green;width: 200px;height: 200px" @click.capture.stop="log(2)" @click="log(2)">
        <div style="background: blue;width: 150px;height: 150px" @click.capture="log(3)" @click="log(3)">
            <div style="background: black;width: 100px;height: 100px" @click.capture="log(4)" @click="log(4)">
            </div>
        </div>
    </div>
</div>

将输出:1 2 后续由于事件传递被阻止,将不再触发

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wflynn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值