JS事件传播机制浅析(事件捕获与事件冒泡)
很久以来一直对js事件传播机制搞的一塌糊涂,项目中用到时去各种度娘顾狗,虽也能做出产品,但总不能熟记于心。今日姑且做个demo加深记忆。
W3C标准的JS事件传播包含事件捕获和事件冒泡,而非标准的JS事件传播(IE)则只支持事件冒泡。下面就从W3C的标准事件传播开始说:
事件的传播是从事件捕获开始的,到达目标dom 节点(绑定相关事件句柄的dom节点) 后,执行相关的事件句柄,然后开始冒泡回传。事件捕获是从dom根节点(document)开始一层层的往子节点的方向捕获,直到捕获到相关事件句柄,而事件冒泡是从当前节点往父节点方向冒泡传播的。
W3C 支持事件捕获的事件绑定方法:addEventListener(type,fn,useCapture); useCapture就是用来设置是否支持事件捕获的参数。阻止事件传播可以用e.stopPropagation();一旦调用的stopPropagation事件传播将会被阻断,不会按着既定的方向继续传播了。
下边举一系列的例子:
#1全部阻止事件捕获
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
<div id="child" style="padding:100px;border:1px solid #333333;">
<div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
</div>
</div>
<script>
var $=function(id){
return document.getElementById(id);
};
function alertP(e){
alert("Parent");
}
function alertC(){
alert("Child");
}
function alertG(e){
alert("Grandson");
}
$("parent").addEventListener("click",alertP,false);
$("child").addEventListener("click",alertC,false);
$("grandson").addEventListener("click",alertG,false);
</script>
</body>
</html>
点击最里层的div,弹出的内容顺序是:
Grandson,Child,Parent
因为我们这里把useCapture都设置成了false,就是意味着不要应用事件捕获的过程,直接冒泡。事件是从最里层向最外层(子-》父)冒泡的。
#2全部支持事件捕获
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
<div id="child" style="padding:100px;border:1px solid #333333;">
<div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
</div>
</div>
<script>
var $=function(id){
return document.getElementById(id);
};
function alertP(e){
alert("Parent");
}
function alertC(){
alert("Child");
}
function alertG(e){
alert("Grandson");
}
$("parent").addEventListener("click",alertP,true);
$("child").addEventListener("click",alertC,true);
$("grandson").addEventListener("click",alertG,true);
</script>
</body>
</html>
点击最里层的div,弹出的内容顺序是:
Parent,Child,Grandson
这是因为useCapture设为true,意味着支持事件捕获,事件捕获是从父节点往子节点方向开始捕获的。
#3.部分支持事件捕获
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
<div id="child" style="padding:100px;border:1px solid #333333;">
<div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
</div>
</div>
<script>
var $=function(id){
return document.getElementById(id);
};
function alertP(e){
alert("Parent");
}
function alertC(){
alert("Child");
}
function alertG(e){
alert("Grandson");
}
$("parent").addEventListener("click",alertP,false);
$("child").addEventListener("click",alertC,true);
$("grandson").addEventListener("click",alertG,false);
</script>
</body>
</html>
点击最里层的div,弹出的内容顺序是:
Child,Grandson,Parent;
#4.阻断事件传播
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
<div id="child" style="padding:100px;border:1px solid #333333;">
<div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
</div>
</div>
<script>
var $=function(id){
return document.getElementById(id);
};
function alertP(e){
alert("Parent");
}
function alertC(){
alert("Child");
}
function alertG(e){
alert("Grandson");
e.stopPropagation();
}
$("parent").addEventListener("click",alertP,false);
$("child").addEventListener("click",alertC,true);
$("grandson").addEventListener("click",alertG,false);
</script>
</body>
</html>
点击最里层的div,弹出的内容顺序是:
Child,Grandson;
这里是冒泡的过程被阻断的;
#5.这个阻断多次一举
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
<div id="child" style="padding:100px;border:1px solid #333333;">
<div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
</div>
</div>
<script>
var $=function(id){
return document.getElementById(id);
};
function alertP(e){
alert("parent");
e.preventDefault();
}
function alertC(){
alert("Child");
e.stopPropagation();
}
function alertG(e){
alert("Grandson");
}
// $("parent").onclick=alertP;
// $("child").onclick=alertC;
// $("grandson").onclick=alertG;
$("parent").addEventListener("click",alertP,true);
$("child").addEventListener("click",alertC,false);
$("grandson").addEventListener("click",alertG,true);
</script>
</body>
</html>
点击最里层的div,弹出的内容顺序是:
Parent,Grandson,Child;
#6.阻止捕获和阻断传播混用
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Event Propagation Test</title>
</head>
<body>
<div id="parent" style="padding:100px;border:1px solid #333333;">
<div id="child" style="padding:100px;border:1px solid #333333;">
<div id="grandson" style="padding:100px;border:1px solid #333333;"></div>
</div>
</div>
<script>
var $=function(id){
return document.getElementById(id);
};
function alertP(e){
alert("parent");
e.preventDefault();
}
function alertC(){
alert("Child");
}
function alertG(e){
alert("Grandson");
e.stopPropagation();
}
// $("parent").onclick=alertP;
// $("child").onclick=alertC;
// $("grandson").onclick=alertG;
$("parent").addEventListener("click",alertP,true);
$("child").addEventListener("click",alertC,false);
$("grandson").addEventListener("click",alertG,true);
</script>
</body>
</html>
点击最里层的div,弹出的内容顺序是:
Parent,Grandson;
IE中则只有事件冒泡的过程,就是只有从子节点向父节点回传的过程,阻断事件传播可以用event.cancelBubble.这里就不在多举测试例子
此外,W3C标准的事件模型中e.preventDefault也非常有用,它主要是用来阻止事件的默认行为发生.IE中与它相对应的是window.event.returnValue=false;
posted on 2014-05-25 01:04 Young_Junior_Man 阅读(252) 评论(0) 收藏 举报
浙公网安备 33010602011771号