JavaScript的事件是个很神奇的东西,具有穿透功能。
举个例子,桌子上有一本书,用手拍书,其实也是在拍桌子。拍击书本的动作,“穿透”到了桌子上了。
不过JavaScript事件是怎么运作的?
一图看懂。
由此可以知道
1、一个完整的JS事件流是从window开始,最后回到window的一个过程
2、事件流被分为三个阶段(1~5)捕获过程、(5~6)目标过程、(6~10)冒泡过程
“捕获阶段”,可以理解为捕鱼,从河面上撒网,从上到下“穿透”。
“冒泡阶段”,可以理解为水中气泡往上冒,从下到上“穿透”。
为了说明这个过程,举个例子。
<style>
.parent{
width: 300px;
height: 300px;
background: #f00;
color: #fff;
}
.child{
width: 200px;
height: 200px;
background: #ffff00;
margin-left: auto;
margin-right: auto;
color: #000;
}
</style>
<div id="parent" class="parent">
父标签
<div id="child" class="child">
子标签
</div>
</div>
let parent = document.getElementById("parent");
let child = document.getElementById("child");
parent.addEventListener("click",function(){
console.info("parent-捕获");
},true); // 捕获阶段发生
parent.addEventListener("click",function(){
console.info("parent-冒泡");
},false); // 默认,冒泡阶段发生
child.addEventListener("click",function(){
console.info("child-捕获");
},true); // 捕获阶段发生
child.addEventListener("click",function(){
console.info("child-冒泡");
},false); // 默认,冒泡阶段发生
可以看到,捕获阶段的事件是先于冒泡阶段发生的。
一般应用事件的时候,不会在意点了什么。不过有时候,必须要知道当前事件发生在哪个标签上。
这个时候就要用到event事件对象了。
event对象的两个属性target和currentTarget。target表示触发事件的标签,但是不一定是添加事件的标签;而currentTarget则是指添加事件的标签。
还是上面这个例子,修改JavaScript代码如下,只给父标签添加点击事件,分别输出event对象的target和currentTarget。
let parent = document.getElementById("parent");
let child = document.getElementById("child");
parent.addEventListener("click",function(){
console.info( event.target );
console.info( event.currentTarget );
});
可以看到,点击红色父标签的部分,得到的两个输出都是一样的,都是父标签。
但是,如果点击子标签的话,target得到的是子标签,因为点了子标签,是通过子标签触发了事件;而currentTarget得到的还是父标签,因为事件是添加在它上面的。
当然,在实际的运用中可能没考虑的这么麻烦。一般只在意的是事件的冒泡。就是说,我点击子标签的时候,不希望父标签的点击事件也发生。这个时候,我们就需要阻止事件冒泡。
let parent = document.getElementById("parent");
let child = document.getElementById("child");
child.addEventListener("click",function(event){
console.info("child");
event.stopPropagation() ; // 阻止冒泡
});
parent.addEventListener("click",function(){
console.info("parent");
});
event.stopPropagation() ;
就可以成功阻止事件冒泡。