JS 冒泡和捕获是怎么回事
看网上说的也不是太明白,我给重新整理下。 参阅:https://www.cnblogs.com/alvin...
冒泡和捕获是指在元素上的事件被触发的时候,js 传递事件的两种方向,或者说过程。
前言:
如,有这么一个页面 和 js 方法
Less: 我用 less写的,如果没有 less 环境,可以无视这段。
.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)}
#lv4{ .level-template(4)}
HTML
<div id="lv1" class="level">
<div id="lv2" class="level">
<div id="lv3" class="level">
<div id="lv4" class="level">
</div>
</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
包含 lv2
,lv2
又包含 lv3
,当点击 lv3
的时候,其实也点击了 lv2
和 lv1
,因为 lv3
在 lv2
内部,点击 lv3
的时候,自然也点击了 lv2
和 lv1
,也就是说,点击 lv3
的时候,会触发三个 click
事件。
至于这三个事件触发的顺序,就是所谓的 冒泡
和 捕获
。
事件触发经过的三个阶段:
-
捕获阶段:先由文档的根节点
document
往事件触发对象,从外向内捕获事件对象; - 定位目标:寻找到目标事件位置(事发地),触发事件;
- 冒泡阶段:再从目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象。
1. 捕获阶段
如上面的例子,在 lv3
被点击的时候,js 会从文档的最上层开始,由外向内寻找点击事件的起源,也就是 lv3
。那么这个由外向内的过程就是 lv1
--> lv2
--> lv3
,这三个 div 的 click 事件按照这个过程依次被触发。
这个触发的方向就是捕获
的方向。
2. 冒泡阶段
在找到被点击的 lv3 之后,事件向上传递,过程是 lv3
--> lv2
--> lv1
,此时依次触发 lv3
、lv2
、lv1
的 click
事件,这个由内向外的触发过程就称为冒泡
再回看一下最常用的事件绑定方法的格式:
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
总结
冒泡和捕获的关系,只会出现在包含和被包含的结构中,兄弟关系是不会有这种关系的。
冒泡和捕获只是方向的不同而已。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。