一.事件流
事件纳胧,是文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬間镰吆。
事件流,描述的是頁面中接受事件的順序跑慕。
IE9万皿,chrome,F(xiàn)irefox核行,Opera牢硅,Safari均實現(xiàn)了DOM2級規(guī)范中定義的標(biāo)準(zhǔn)DOM事件,而IE8和IE8以下版本仍然保留專有的事件處理方式
1.事件冒泡
事件冒泡芝雪,即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節(jié)點)接收减余,然后逐級向上傳播。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Event Bubbling Example</title>
</head>
<style type="text/css">
#myDiv{
width:100px;
height:100px;
background-color:#FF0000;
}
</style>
<body>
<div id="myDiv"></div>
</body>
<script type="text/javascript">
var div=document.getElementById("myDiv");
div.onclick=function(event){
alert("div");
};
document.body.onclick=function(event){
alert("body");
};
</script>
</html>
點擊<div>惩系,將先輸出“div”位岔,再輸出“body”。
IE9蛆挫,chrome赃承,F(xiàn)irefox妙黍,Opera悴侵,Safari都支持事件冒泡,并將事件冒泡到window對象拭嫁。
2.事件捕獲
事件捕獲是由Netscape Communicator團隊提出來的可免,是先由最上一級的節(jié)點先接收事件抓于,然后向下傳播到具體的節(jié)點。當(dāng)用戶點擊了<div>元素浇借,采用事件捕獲捉撮,則click事件將按照document—><html>—><body>—><div>的順序進(jìn)行傳播。
若在<div>和<body>上都定義了click事件妇垢,如下:
var div=document.getElementById("myDiv");
div.addEventListener("click",function(event){
alert("div");
},true);
document.body.addEventListener("click",function(event){
alert("body");
},true);
點擊<div>巾遭,將先輸出“body”,再輸出“div”闯估。
IE9灼舍,chrome,F(xiàn)irefox涨薪,Opera骑素,Safari都支持事件捕獲,但是IE8和IE8以下的版本只支持事件冒泡刚夺。盡管DOM2規(guī)范要求事件應(yīng)該從document對象開始傳播献丑,但是現(xiàn)在的瀏覽器實現(xiàn)都是從window對象開始捕獲事件。
DOM事件流
"DOM2級事件”規(guī)定的事件流包含三個階段:事件捕獲階段侠姑,處于目標(biāo)階段和事件冒泡階段创橄。首先發(fā)生的是事件捕獲,然后是實際的目標(biāo)接收到事件莽红,最后階段是冒泡階段筐摘。以上面的HTML頁面為例,單擊<div>元素將按照下圖觸發(fā)事件:
<script type="text/javascript">
var div=document.getElementById("myDiv");
div.onclick=function(event){
alert("div");
};
document.body.addEventListener("click",function(event){
alert("冒泡");
},false);
document.body.addEventListener("click",function(event){
alert("捕獲");
},true);
</script>
點擊<div>船老,將先輸出“捕獲”咖熟,再輸出“div”,最后輸出“冒泡”柳畔。
二.事件處理程序
事件是用戶或瀏覽器自身執(zhí)行的某種動作馍管,而響應(yīng)某個事件的函數(shù)叫做事件處理程序。HTML事件處理程序薪韩、DOM0級事件處理程序和IE事件處理程序均以“on”開頭确沸,DOM2級事件處理程序不需要加“on”。
<div onclick="alert('我被點擊了')">我是通過屬性添加的事件</div>
DOM0級事件處理程序
通過Javascript指定事件處理程序的傳統(tǒng)方式俘陷,所有瀏覽器均支持罗捎。每個元素(包括window,document)都有自己的事件處理程序?qū)傩岳埽潜仨氃贒OM節(jié)點加載完之后才會有效桨菜。如下所示:
var div=document.getElementById("myDiv");
div.onclick=function(event){
alert("div");
};
使用DOM0級方法指定的事件處理程序被認(rèn)為是元素的方法,在元素的作用域中運行。this引用當(dāng)前元素倒得,如下:
var div=document.getElementById("myDiv");
div.onclick=function(event){
alert(this.id);
};
輸出“myDiv”泻红。
刪除通過DOM0級方法指定的事件處理程序:div.onclick=null;
DOM2級事件處理程序
IE9,chrome霞掺,F(xiàn)irefox谊路,Opera,Safari均實現(xiàn)了DOM2級事件處理程序菩彬,綁定事件方法addEventListener()接收三個參數(shù):事件名稱缠劝,事件處理函數(shù)和一個布爾值。布爾值為true骗灶,則表示在捕獲階段調(diào)用事件處理程序剩彬;如果為false,則表示在冒泡階段調(diào)用事件處理程序矿卑。addEventListener允許在同一個元素上添加多個事件處理程序喉恋,如下所示:
var div=document.getElementById("myDiv");
div.addEventListener("click",function(event){
alert("冒泡");
},false);
div.addEventListener("click",function(event){
alert("捕獲");
},true);
先輸出“冒泡”,后輸出“捕獲”母廷,說明addEvenListener綁定的處理程序執(zhí)行順序和綁定順序相同轻黑。
通過DOM2級事件處理程序指定的方法,this也引用當(dāng)前元素琴昆,如下:
div.addEventListener("click",function(event){
alert(this.id);
},false);
輸出“myDiv”氓鄙。
刪除DOM2級事件處理程序,采用removeEventListener()业舍,刪除時傳入的參數(shù)必須和綁定時傳入的參數(shù)相同抖拦,不能傳入匿名函數(shù)。如下所示:
var div = document.getElementById("myDiv");
var handler=function(event){
alert("delete");
};
div.addEventListener("click",handler,false);
div.removeEventListener("click",handler,false);
IE事件處理程序
var div = document.getElementById("myDiv");
div.attachEvent("onclick", function(event) {
alert("1");
});
div.attachEvent("onclick", function(event) {
alert("2");
});
IE9和IE10先輸出“1”舷暮,再輸出“2”态罪,而IE8和IE7先輸出“2”,再輸出“1”下面。
刪除IE事件處理程序复颈,采用detachEvent(),刪除時傳入的參數(shù)必須和綁定時傳入的參數(shù)相同沥割,不能傳入匿名函數(shù)耗啦。如下所示:
<script>
var div = document.getElementById("myDiv");
var handler = function(event) {
alert("delete");
};
div.attachEvent("onclick",handler);
div.detachEvent("onclick",handler);
</script>
總結(jié):attachEvent()采用冒泡方式,而addEventListener()可以采用冒泡或事件捕獲方式机杜。
先按由上往下的順序執(zhí)行事件捕獲的執(zhí)行程序帜讲,再執(zhí)行目標(biāo)元素的執(zhí)行程序,最后按由下往上的順序執(zhí)行冒泡事件椒拗。代碼如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#child {
width: 100px;
height: 100px;
background-color: #FF0000;
}
</style>
</head>
<body>
<div id="myDiv"></div>
<div id="parent">
<div id="child"></div>
</div>
</body>
<script>
var parent = document.getElementById("parent");
var child = document.getElementById("child");
child.onclick = function(event) {
alert("child");
};
document.body.addEventListener("click", function(event) {
alert("body:捕獲");
}, false);
document.body.addEventListener("click", function(event) {
alert("body:冒泡");
}, true);
parent.addEventListener("click", function(event) {
alert("parent:冒泡");
}, true);
parent.addEventListener("onclick", function(event) {
alert("parent:捕獲");
});
</script>
</html>
輸出順序:body:捕獲—>parent:冒泡—>child—>parent:捕獲—>body:冒泡