今天来谈谈Js中事件捕获与冒泡的问题。。。
事件捕获与冒泡,实际上是事件传播的两种方向。说实话“捕获”和“冒泡”这两个词语已经够形象生动了,我们从这两个词语的字面意思就应该清楚。
事件捕获就像电影中的捕猎行动一样,从一个大的范围逐渐缩小范围直至找到狩猎目标,在Js事件的传播过程中,也是这样,举个例子:window-document-html-body-div-p这个方向就是从大范围到小范围的一个方向,这个就称为事件的捕获。
事件冒泡就像我们观察水中的气泡上升一样,从最底层逐渐地上升到表面,在Js事件的传播过程中,也是这样,举个例子:p-div-body-html-document-window,可以很明显看到这个方向正好与事件捕获的方向相反,这个就称为事件的冒泡。
到这里,或许就有人问了,花这大工夫来研究这劳什子东西,有什么用啊?我想说还不是各大浏览器标准不一致给闹的啊!
以上例来说明,如果你在div和p上同时绑定了click事件,点击p后到底是哪个先触发?
好了,不卖关子了,在Netscape中,div先触发;在Microsoft中,会p先触发。
(ps:IE只支持事件冒泡,Mozilla, Opera 7和Konqueror两种都支持,旧版本的Opera's和iCab两种都不支持 )
我们知道IE与!IE绑定事件的方法不同,
v IE是attachEvent(event,Fn);event:监听事件类型,Fn:处理函数,只支持冒泡模式
attachEvent中的监听事件类型,要加前缀“on”;
v !IE是addEventListener(event,Fn,[boolean]);event:监听事件类型,Fn:处理函数,可选布尔值:true:捕获模式,false:冒泡模式,由于IE不支持捕获模式,故通常我们将布尔值默认设为false。
那有人会问了,div与p同时绑定‘click’事件后,我只想点击p的时候只显示有关p的内容,而屏蔽div的点击事件,能不能做到呢?
答案当然是肯定的,我们只需要在绑定事件时,做一个事情,那就是
v IE,在设置绑定时,为底层元素添加属性,cancelBubble = true,就好了;
v !IE,在设置绑定时,为底层元素添加方法,stopPropagation(),就好了;
最后附上一段代码,供大家参考:
<div id="div" style="width:100px;height: 100px;background-color: blue;">
<p id="p" style="width:40px;height: 40px;margin:auto;background-color: yellow;">
</p>
</div>
<script>
var div = document.getElementById('div');
var p = document.getElementById('p');
var DivFn = function(e){
alert('Div');
}
var PFn = function(e){ /*阻止冒泡*/
var event = window.event||e;
if(window.event){ //IE
event.cancelBubble = true;
}else{
event.stopPropagation(); //ff
}
alert('p');
}
if(div.addEventListener){ //!IE
div.addEventListener('click',DivFn);
p.addEventListener('click',PFn);
}else{ //IE
div.attachEvent('onclick',DivFn);
p.attachEvent('onclick',PFn);
}
</script>