首页 > 技术文章 > js事件冒泡与捕捉解析

ycherry 2017-07-26 11:37 原文

js的事件的冒泡与捕捉,简单来说就像个V型,从最高层body开始捕捉事件,然后一层一层往下开始捕捉,底层捕捉到事件后进行处理,然后再一层层冒泡传给父级,父级再传到它的父级,如果没有阻止冒泡,事件会一直传回给body,整个下来如下图所示:

 

下面的例子可以证明事件的冒泡与捕捉的过程:
在此例中我们用到一个js函数:
addEventListener(event,listener,userCapture)
其中:event:就是监听的事件 listener:即要执行监听的函数 userCapture: false的时候是冒泡, true表示是捕获。


1.事件捕获
A:
<!DOCTYPE html>
<html>
<head>
<title>bubble</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
#parent {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div id="parent">
parent
<button id="child">child</button>
</div>
<script>
var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.body.addEventListener("click",function(e){
console.log("body-capture");
},true);
parent.addEventListener("click",function(e){
console.log("parent-capture");
},true);
child.addEventListener("click",function(e){
console.log("child-capture");
},true);
</script>
</body>
</html>
上面代码输出的结果是:
body-capture
parent-capture
child-capture
说明事件的捕获是从上级往下捕获的。


2.事件冒泡
B:
<!DOCTYPE html>
<html>
<head>
<title>bubble</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
#parent {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div id="parent">
parent
<button id="child">child</button>
</div>
<script>
var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.body.addEventListener("click",function(e){
console.log("click-body");
},false);
parent.addEventListener("click",function(e){
console.log("click-parent");
},false);
child.addEventListener("click",function(e){
console.log("click-child");
},false);
</script>
</body>
</html>

输出结果:
click-child
click-parent
click-body
事件冒泡从下级往上级冒泡

将上面的代码整合起来:
C:
出<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<title>bubble</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
#parent {
width: 200px;
height: 200px;
background-color: green;
}
</style>
</head>
<body>
<div id="parent">
parent
<button id="child">child</button>
</div>
<script>
var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.body.addEventListener("click",function(e){
alert("click-body");
},false);
parent.addEventListener("click",function(e){
alert("click-parent");
},false);
child.addEventListener("click",function(e){
alert("click-child");
},false);
document.body.addEventListener("click",function(e){
alert("body-capture");
},true);
parent.addEventListener("click",function(e){
alert("parent-capture");
},true);
child.addEventListener("click",function(e){
alert("child-capture");
},true);
</script>
</body>
</html>
输结果:
body-capture
parent-capture
click-child
child-capture (为神么到child是先执行冒泡,再执行捕获,这点我还没搞懂)
click-parent
click-body
事件是先捕获后冒泡,如上面所说的V型

3.阻止冒泡/阻止捕获

阻止冒泡需要 stopPropogation()函数
上栗B处代码,如果要在child执行完之后,阻止像parent冒泡则只需要将:
child.addEventListener("click",function(e){
console.log("click-child");
},false);
改为:
child.addEventListener("click",function(e){
console.log("click-child");
e.stopPropagation();
},false);

此时输出的结果就是:
click-child

阻止捕获也是同样方法,用stopPropogation()函数

将上栗A中的代码:
document.body.addEventListener("click",function(e){
console.log("click-body");
},false);
改为:
document.body.addEventListener("click",function(e){
console.log("body-capture");
e.stopPropagation();
},true);
则输出的结果是:
body-capture
body的下级就不能捕捉事件,捕捉不到事件,自然也就不能冒泡了。


以上是我对事件的冒泡和捕捉的理解,没有考虑不同浏览器对其的支持,以及不同浏览器处理的差别问题。
如有错误,欢迎指出
如有问题,欢迎提问

推荐阅读