1.什么是事件冒泡
如图:现在有3个嵌套div,且都有onclick事件,当div_3被单击时,依次触发div_3=>div_2=>div_1的click事件。
这就是事件冒泡:当一个事件被触发时,依次由最上层元素(div_3)向下遍历并执行该元素及父元素相同事件的过程就是事件冒泡。
2.什么是事件捕获
3.为什么会有事件冒泡与事件捕获
如图,冒泡事件之所存在与js的事件处理机制有关,事件的触发过程是这样:
i:某元素事件被触发,会找到其父元素及祖父元素直至根元素,并组成“树”
ii:从“树”根元素向上寻找父元素,若父元素包含有该事件且注册事件的userCapture参数为true(这个属性下文会讲到)便触发
iii:继续向上遍历寻找父元素的父元素,并进行相同的判断,直至正真触发事件的“顶层”元素(到此为止的过程便是事件捕获过程)
iiii:到达“顶部”之后,再往下从“叶子”往“根”再次遍历(事件冒泡开始),若元素包含有该事件且注册事件的userCapture参数为false便触发
v:不断遍历,到根部结束(事件冒泡结束)
这就产生了事件冒泡与事件捕获的概念。
3.实验
先看代码,我们加了3个div(运行结果与上文第一幅图相同):
<html>
<head>
<script>
function init(){
document.getElementById("div_1").addEventListener("click",function (){alert(this.id);},true);
document.getElementById("div_2").addEventListener("click",function (){alert(this.id);},true);
document.getElementById("div_3").addEventListener("click",function (){alert(this.id);},true);
}
</script>
</head>
<body onload="init()">
<div id="div_1" style="background-color:#FFF200; 150px;height:150px" > div_1 <br/>
<div id="div_2" style="background-color:#EFE4B0; 120px;height:120px; margin-left:15px;" > div_2 <br/>
<div id="div_3" style="background-color:#B5E61D; 90px;height:90px; margin-left:15px; " > div_3<br/><br/>
click me!
</div>
</div>
</div>
</body>
</html>
现在:单击div_3看看会怎样?
结果:依次弹出“div_1”=>“div_2”=>"div_3"
我们注意到这里用了一个函数addEventListener();他的作用是为元素注册事件,你可以将它理解为与οnclick=“xxx()” 类似,但是任有区别(区别参考这里)
他有3个参数,分别是:eventType:表示事件类型
function:触发事件将执行的函数
userCapture:是否执行捕捉
前两个参数从字面就可以理解,但是第三个参数值什么意思?
所谓执行捕捉,是指在事件捕获的过程中需要触发的事件,若该参数为false则只会触发事件冒泡,若为true,则只会触发事件捕获。
为了验证,我们修改上面的init()函数,如下:
function init(){
document.getElementById("div_1").addEventListener("click",function (){alert(this.id);},false);
document.getElementById("div_2").addEventListener("click",function (){alert(this.id);},true);
document.getElementById("div_3").addEventListener("click",function (){alert(this.id);},false);
}
将div_1与div_3的userCapture参数改为false。这样,按照我们上面的定义,这次单击div_3弹框顺序应该是:div_2=>div_3=>div_1.
经测试,确实如此 :)
4.对我们的好处及缺点
<html>
<head>
<script>
function init(){
document.getElementById("div_1").addEventListener("click",function (){
var target =getAimEle();
alert(target.id);
},false);
}
function getAimEle(){
var ele=window.event;
return ele.target==null? ele.srcElement:ele.target;
}
</script>
</head>
<body onload="init()">
<div id="div_1" style="background-color:#FFF200; 150px;height:150px" > div_1 <br/>
<div id="div_2" style="background-color:#EFE4B0; 120px;height:120px; margin-left:15px;" > div_2 <br/>
<div id="div_3" style="background-color:#B5E61D; 90px;height:90px; margin-left:15px; " > div_3<br/><br/>
click me!
</div>
</div>
</div>
</body>
</html>
这时候,单击div_3,会弹出"div_3",而我们并没有特意为他注册事件。
5.如何消除冒泡与捕获
<html>
<head>
<script>
function init(){
document.getElementById("div_1").addEventListener("click",function (){alert(this.id);},false);
document.getElementById("div_2").addEventListener("click",function (){
alert(this.id);
var e=window.event;
if(e.cancelBubble!=null) e.cancelBubble=true;
else e.stopPropagation();
;},false);
document.getElementById("div_3").addEventListener("click",function (){alert(this.id);},false);
}
</script>
</head>
<body onload="init()">
<div id="div_1" style="background-color:#FFF200; 150px;height:150px" > div_1 <br/>
<div id="div_2" style="background-color:#EFE4B0; 120px;height:120px; margin-left:15px;" > div_2 <br/>
<div id="div_3" style="background-color:#B5E61D; 90px;height:90px; margin-left:15px; " > div_3<br/><br/>
click me!
</div>
</div>
</div>
</body>
</html>
单击div_3,效果是:div_3=>div_2