DOM事件流分为三种
1.捕获事件
2.当前目标阶段
3.冒泡阶段
简单说,事件流就是规定执行顺序,大的先执行还是小的先执行。
js代码一次只能执行捕获和冒泡中的一个。
我们先设置一下html的代码
<div class="father">
<div class="son">son盒子</div>
</div>
这里设置了两个盒子,父盒子father包含子盒子son。
哪么,如何开启捕获呢
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, true);
正常情况来看,这是给子盒子son一个点击事件,点击之后弹出son。
但是第三个参数多了个true,这就是开启捕获的开关。
捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段 document -> html -> body -> father -> son,从大到小。
由于我们只给son设置了点击事件,所以只有点击son时会弹出son,似乎没啥用哎?
那我们在给father一个点击事件
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, true);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, true);
那现在我们点击这个盒子的的时候,是谁先弹出来呢?
答案是先弹出father再弹出son,因为捕获是从大到小的,而son又是father的子盒子,点击son也会顺带点击了father的区域,也会顺带点击了body的区域,也会顺带点击了html的区域,以此类推。
捕获事件就是让大的父亲先运行。
如果没有这个事件流区分,那就像班级里没有老师,他们会同时弹出,但是浏览器无法满足同时弹出,会乱套的,所以才有了事件流这个东西来规定约束。
---------------------------------------------------------------------------------------------------------------------------------
那,冒泡事件呢?
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
同理,后面把true改成false,子盒子先执行,最后执行最大的盒子。
注意,如果true和false都不给,则默认开启冒泡,子盒子有优先执行权
那怎么取消冒泡呢?
因为默认就是冒泡,有时候也会带给我们很多不好的地方。
//第一种
e.stopPropagation(); // stop 停止 Propagation 传播
//第二种
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡,兼容i678设置的
只需要在侦听函数中加这两个其中一个就可以了。