JS 什么是 冒泡 和 捕获 capture pop

JS 冒泡和捕获是怎么回事 capture pop

看网上说的也不是太明白,我给重新整理下。 参阅:https://www.cnblogs.com/alvinwei1024/p/4739344.html

冒泡和捕获是指在元素上的事件被触发的时候,js 传递事件的两种方向,或者说过程。


前言:

如,有这么一个页面 和 js 方法

在这里插入图片描述

scss: 我用 scss 写的,如果没有 scss 环境,可以无视这段。

.level {
  padding: 50px 80px;
}

.level-template($level: 1, $color: #fff){
  background-color: darken( $color , 5% * $level);
}

#lv1{ .level-template(1)}
#lv2{ .level-template(2)}
#lv3{ .level-template(3)}

HTML

<div id="lv1" class="level">
    <div id="lv2" class="level">
        <div id="lv3" class="level">
        
        </div>
    </div>
</div>

JS

function $(id) {
    return document.getElementById(id);
}

window.onload = () => {
    $('lv1').addEventListener("click",()=>{console.log('lv1')},true);
    $('lv2').addEventListener("click",()=>{console.log('lv2')},true);
    $('lv3').addEventListener("click",()=>{console.log('lv3')},true);
};
// 上面的 () => {} 为 ES6 的匿名方法的定义方式
// 等同于
function () {
	console.log('lv1')
}

上面的 js 做的事:
在页面载入的时候,给三个 div 添加 click 监听方法,自己被点击的时候会在 console 中输出自己的 id 值。

页面的结构是这样的 lv1 包含lv2lv2 又包含 lv3,当点击 lv3 的时候,其实也点击了lv2lv1,因为 lv3lv2 内部,点击 lv3 的时候,自然也点击了 lv2lv1,也就是说,点击 lv3 的时候,会触发三个 click 事件。
至于这三个事件触发的顺序,就是所谓的 冒泡捕获


事件触发经过的三个阶段:

  1. 捕获阶段:先由文档的根节点 document 往事件触发对象,从外向内捕获事件对象;
  2. 定位目标:寻找到目标事件位置(事发地),触发事件;
  3. 冒泡阶段:再从目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象。

1. 捕获阶段

如上面的例子,在 lv3 被点击的时候,js 会从文档的最上层开始,由外向内寻找点击事件的起源,也就是 lv3。那么这个由外向内的过程就是 lv1 --> lv2 --> lv3,这三个 div 的 click 事件按照这个过程依次被触发。
这个触发的方向就是捕获的方向。

2. 冒泡阶段

在找到被点击的 lv3 之后,事件向上传递,过程是 lv3 --> lv2 --> lv1,此时依次触发 lv3lv2lv1click 事件,这个由内向外的触发过程就称为冒泡


再回看一下最常用的事件绑定方法的格式:

element.addEventListener(event, function, useCapture)

这里面,useCapture 是个布尔值,用于定义事件是在冒泡阶段触发,还是在捕获阶段触发,默认值是 false,代表在冒泡时触发。


此时你就会知道上面那个例子里定义的 click 方法是在 捕获阶段 执行,那么返回的结果就是

lv1
lv2
lv3

如果最上面的例子,onload 内容是这样的

 window.onload = () => {
        $('lv1').addEventListener("click",()=>{console.log('lv1')},false);
        $('lv2').addEventListener("click",()=>{console.log('lv2')},false);
        $('lv3').addEventListener("click",()=>{console.log('lv3')},false);
    };

那么也就是说, click 事件在 冒泡阶段触发,返回的结果就是

lv3
lv2
lv1

vue 中对事件传递方向的控制

举个例子,像下面这个页面中,我在列表项整体添加了点击方法,也在上下移动按钮上加了点击方法。
请添加图片描述
现在的情况是,我点击上下移动按钮时,也会触发列表项的点击方法。
为什么? 因为不管冒泡还是捕获方向,触发是没有停止的。
如果需要在点击上下移动按钮时,不触发列表的点击事件,就需要给上下按钮上添加 @click.stop="clickMethod" 添加 .stop 修饰符,意思是停止事件向外传播,
因为没有使用 .capture 修饰符,就表示事件目前是从子元素向外传递的。
如果你在列表项加添加 .capture.stop 就无法触发上下按钮的方法了,因为在捕获方向上,由外层向子层的时候已经被外面的元素截获并停止了这个事件的传递。

总结

冒泡和捕获的关系,只会出现在包含和被包含的结构中,兄弟关系是不会有这种关系的。
冒泡和捕获只是方向的不同而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十月ooOO

许个愿,我帮你实现

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

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

打赏作者

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

抵扣说明:

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

余额充值