引子:
父div添加監(jiān)聽事件界逛,子div設(shè)置監(jiān)聽事件昆稿,點擊子元素,會出現(xiàn)什么結(jié)果
事件傳播的三個過程息拜,事件捕獲階段溉潭、處于目標(biāo)階段、事件冒泡階段少欺。
事件捕獲由遠(yuǎn)及近逐漸靠近事件目標(biāo)喳瓣,事件冒泡由事件目標(biāo)逐漸向上冒泡
那是不是所有的事件都要經(jīng)歷這三個過程呢?其實不然
IE:它認(rèn)為事件流應(yīng)該是事件冒泡赞别。
Netscape:它則認(rèn)為事件流應(yīng)該是事件捕獲畏陕。
W3C:首先是事件捕獲然后事件冒泡
在支持w3c的瀏覽器中,程序員可以通過設(shè)置addEventListener(type,handler,useCapture)中的userCapture值來決定元素是在冒泡階段執(zhí)行事件還是捕獲階段執(zhí)行仿滔,默認(rèn)為false惠毁,即冒泡階段。
IE沒有提供選擇堤撵,事件只能在冒泡階段捕獲仁讨。
偷個圖[https://www.w3cin.com/2016/06/03/%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84DOM%E4%BA%8B%E4%BB%B6/]:
IE9羽莺、Opera实昨、Firefox、Chrome和Safari都支持DOM事件流盐固。
寫個代碼測試一下
頁面內(nèi)容很簡單荒给,父div子div
<div id="parent">
parent
<div id="child">child</div>
</div>
因為考慮到瀏覽器兼容性丈挟,先寫一個跨瀏覽器事件處理函數(shù)
var eventHandler={
addEventHandler:function(ele,type,handler,capture){
if(ele.addEventListener){
ele.addEventListener(type,handler,capture);
}else if(ele.attachEvent){
//ie下是需要加on的
//ele.attachEvent(type,handler);
ele.attachEvent('on'+type,handler);
}else{
ele['on'+type]=handler;
}
},
stopPropagation:function(event){
event=event||window.event;
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble=true;
}
},
preventDefault:function(event){
event=event||window.event;
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue=true;
}
}
}
進(jìn)入正題,對父子div添加監(jiān)聽函數(shù)
window.onload=function(){
var parent=document.getElementById("parent");
var child=document.getElementById("child");
eventHandler.addEventHandler(parent,'click',function(e){
console.log("parent捕獲階段");
},true);
eventHandler.addEventHandler(parent,'click',function(e){
console.log("parent冒泡階段");
},false);
eventHandler.addEventHandler(child,'click',function(e){
console.log("child冒泡階段");
},false);
eventHandler.addEventHandler(child,'click',function(e){
console.log("child捕獲階段");
},true);
}
chrome下測試結(jié)果:
事件果然是從父div到子div被捕獲志电,然后從子div到父div冒泡曙咽。
注意:此處對子div綁定了兩個事件,即冒泡事件和捕獲事件挑辆,這兩個事件的執(zhí)行順序是按照綁定的先后順序執(zhí)行的例朱,如果把兩個執(zhí)行函數(shù)替換一下,結(jié)果就會先打印child捕獲階段鱼蝉,再打印child冒泡階段洒嗤,不信你試試~
ie8下的測試結(jié)果:
ie下不存在捕獲階段,直接從冒泡階段開始魁亦,由子div到父div打印事件渔隶。此處應(yīng)該注意,對重復(fù)綁定的事件洁奈,在IE9以下的瀏覽器中執(zhí)行順序都是反著的间唉,因為IE9開始已經(jīng)支持addEventListener()方法所以不會在有這個問題了。
比如現(xiàn)在我把事件的執(zhí)行順序改為
eventHandler.addEventHandler(parent,'click',function(e){
console.log("parent捕獲階段");
// eventHandler.stopPropagation(e);
},true);
eventHandler.addEventHandler(parent,'click',function(e){
console.log("parent冒泡階段");
},false);
eventHandler.addEventHandler(child,'click',function(e){
console.log("child捕獲階段");
},true);
eventHandler.addEventHandler(child,'click',function(e){
console.log("child冒泡階段");
},false);
chrome下的執(zhí)行結(jié)果為:
ie8下的執(zhí)行結(jié)果為: