事件冒泡和事件捕获

时间:2021-11-21 05:52:23

JS事件流原理图:

事件冒泡和事件捕获

由此可知道,一个完整的JS事件流是从window开始,最后回到window的一个过程;事件流被分为三个阶段:捕获过程(1~5)、目标过程(5~6)、冒泡过程(6~10);

事实上,捕获过程和冒泡过程是完全相反的过程,即事件由父元素向子元素传播和子元素向父元素传播的过程。

事件捕获

事件捕获在事件绑定的第二种形式下才能实现,事件绑定的第二种形式

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>事件捕获</title>
<style>
div
{padding:40px;}
#div1
{
background
: red;
}
#div2
{
background
:green;
}
#div3
{background: blue;}
</style>
<script>
window.onload
=function(){
var oDiv1=document.getElementById('div1');
var oDiv2=document.getElementById('div2');
var oDiv3=document.getElementById('div3');

function fn1(){
alert(
this.id);
}
//点击div3部分时,分别弹出div1,div2,div3
oDiv1.addEventListener('click',fn1,true);//为true时,是事件捕获 false=冒泡
oDiv2.addEventListener('click',fn1,true);
oDiv3.addEventListener(
'click',fn1,true);
}
</script>
</head>
<body>
<div id="div1">
<div id="div2">
<div id="div3"></div>
</div>
</div>
</body>
</html>

 

 

上面例子中,点击div3时,div1会接收到两个点击事件,一个是在捕获阶段触发了div1的点击事件,一个是在冒泡阶段触发了div1的点击事件;addEventListener中的第三个参数:true----捕获,false-----冒泡;上面设置为true即捕获阶段的点击事件被触发了

注:div1会接收到两个点击事件与是否触发该事件无关

再来个例子:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>事件捕获</title>
<style>
div
{padding:40px;}
#div1
{
background
: red;
}
#div2
{
background
:green;
}
#div3
{background: blue;}
</style>
<script>
window.onload
=function(){
var oDiv1=document.getElementById('div1');
var oDiv2=document.getElementById('div2');
var oDiv3=document.getElementById('div3');


oDiv1.addEventListener(
'click',function(){
alert(
1);
},
false);
oDiv1.addEventListener(
'click',function(){
alert(
3);
},
true);
oDiv3.addEventListener(
'click',function(){
alert(
2);
},
false);
//点击div3,分别弹出3,2,1
}
</script>
</head>
<body>
<div id="div1">
<div id="div2">
<div id="div3"></div>
</div>
</div>
</body>
</html>

 

点击div3,查看弹出的结果分别是:3、2、1

点击div3时,div1会接收到两个点击事件,在捕获阶段(true),触发了div1的点击事件,弹出结果:3;在冒泡阶段,触发了div3的点击事件,弹出结果:2,然后触发了div1的点击事件,弹出结果:1

事件冒泡

当一个元素接受到事件的时候,会把它接收到的所有事件传播给它的父级,一直到顶层window,叫事件冒泡机制;

例子:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>事件冒泡</title>
<style>
div
{padding:40px;}
#div1
{
background
: red;
}
#div2
{
background
:green;
}
#div3
{background: blue;}
</style>
<script>
window.onload
=function(){
var oDiv1=document.getElementById('div1');
var oDiv2=document.getElementById('div2');
var oDiv3=document.getElementById('div3');

function fn1(){
alert(
this.id);
}

//事件函数绑定
oDiv1.onclick=fn1;//告诉div1,如果它接收到了一个点击事件,那它就去执行fn1
oDiv2.onclick=fn1;
oDiv3.onclick
=fn1;//div3,div1 事件冒泡
}
</script>
</head>
<body>
<div id="div1">
<div id="div2">
<div id="div3"></div>
</div>
</div>
</body>
</html>

 

 

阻止冒泡:在当前要阻止冒泡的事件函数中调用event.cancelBubble=true;

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>阻止冒泡</title>
<style>
#div1
{
width
:100px;
height
:200px;
border
:1px solid red;
display
: none;
}
</style>
<script>
window.onload
=function(){
var oBtn=document.getElementById('btn1');
var oDiv=document.getElementById('div1');

oBtn.onclick
=function(ev){
var oEvent=ev||event;
//阻止当前事件函数事件冒泡
oEvent.cancelBubble=true;
oDiv.style.display
='block';
}
document.onclick
=function(){
/* setTimeout(function(){//观察事件冒泡:div出现一秒钟后隐藏了
oDiv.style.display='none';
},1000);
*/
oDiv.style.display
='none';
}
}
</script>
</head>
<body>
<input type="button" value="按钮" id="btn1">
<div id="div1">点击按钮div就出现,点击除按钮以外的部分div就消失</div>
</body>
</html>

 

 

对比没有取消冒泡事件时的效果,下面用了延时器一遍观察效果

 

事件冒泡的运用

下面是一个网站中常见的功能——分享到

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>事件冒泡</title>
<style>
#div1
{
width
:100px;
height
:200px;
background
: red;
position
: absolute;
left
:-100px;
top
:100px;
}
#div2
{
width
:30px;
height
:60px;
position
: absolute;
right
:-30px;
top
:70px;
background
:#000000;
color
:#ffffff;
text-align
: center;
}
</style>
<script>
window.onload
=function(){
var oDiv=document.getElementById('div1');
oDiv.onmouseover
=function(){
this.style.left=0+'px';//鼠标移动到div2时,div2接收到over、out事件时它自己不做,传播给父级div1执行
}
oDiv.onmouseout
=function(){
this.style.left=-100+'px';
}
}
</script>
</head>
<body>
<div id="div1">
<div id="div2">分享到</div>
</div>
</body>
</html>

效果: