** 定義:**
事件:用戶或瀏覽器自身執行的某種動作。
事件流:描述的是從頁面中接收事件的順序,也可理解為事件在頁面中傳播的順序。
事件處理程序:響應某個事件的函數就叫做事件處理程序(或事件偵聽器)。
事件流
**(1)事件冒泡 **
??IE 的事件流叫做事件冒泡(event bubbling),即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節點)接收,然后逐級向上傳播到較為不具體的節點(文檔)。如下圖所示:
IE9、Firefox、Chrome 和 Safari 則將事件一直冒泡到 window 對象。
**(2)事件捕獲 **
??事件捕獲的思想與事件冒泡的思想幾乎完全相反,是不太具體的節點應該更早接收到事件,而最具體的節點應該最后接收到事件。事件捕獲的用意在于在事件到達預定目標之前捕獲它。如下圖所示:
**(3)DOM事件流 **
??“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處于目標階段 和 事件冒泡階段。
- 首先發生的是事件捕獲,為截獲事件提供了機會。
- 然后是實際的目標接收到事件。
- 最后一個階段是冒泡階段,可以在這個階段對事件做出響應。
??在 DOM 事件流中,實際的目標( <div> 元素)在捕獲階段不會接收到事件。這意味著在捕獲階段,事件從 document 到 <html> 再到 <body> 后就停止了。下一個階段是“處于目標”階段,于是事件在 <div>上發生,并在事件處理中被看成冒泡階段的一部分。然后,冒泡階段發生,事件又傳播回文檔。
??IE9,Opera,Firefox,Chrome 和 Safari 都支持 DOM 事件流;IE8 及更早版本不支持 DOM 事件流。
事件處理程序
??響應某個事件的函數就叫做事件處理程序(或事件偵聽器)。事件處理程序的名字以 "on" 開頭,因此click 事件的事件處理程序就是 onclick,load 事件的事件處理程序就是 onload 。為事件指定處理程序的方式有以下幾種:
** (1)HTML事件處理程序 **
<input type="button" value="Click Me" onclick="alert('Clicked')" />
缺點:
- 存在時差問題:因為用戶可能會在HTML 元素一出現在頁面上就觸發相應的事件,但當時的事件處理程序有可能尚不具備執行條件,就會引發錯誤。
- 這樣擴展事件處理程序的作用域鏈在不同瀏覽器中會導致不同結果。不同 JavaScript引擎遵循的標識符解析規則略有差異,很可能會在訪問非限定對象成員時出錯。
- HTML 與 JavaScript 代碼緊密耦合。如果要更換事件處理程序,就要改動兩個地方:HTML 代碼和 JavaScript 代碼。
** (2)DOM0級事件處理程序 **
??即將一個函數賦值給一個事件處理程序屬性。
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("Clicked");
};
btn.onclick = null; //刪除事件處理程序
優點:
- 簡單
- 可跨瀏覽器
** (3)DOM2級事件處理程序 **
addEventListener(事件名稱,事件函數,是否捕獲); //添加事件處理程序
removeEventListener(事件名稱,事件函數,是否捕獲); //移除事件處理程序
所有 DOM 節點中都包含這兩個方法。
優點:可以添加多個事件處理程序。
??通過 addEventListener() 添加的事件處理程序只能使用 removeEventListener() 來移除。所以通過addEventListener()添加的匿名函數將無法移除。
??大多數情況下,都是將事件處理程序添加到事件流的冒泡階段,這樣可以最大限度地兼容各種瀏覽器。最好只在需要在事件到達目標之前截獲它的時候將事件處理程序添加到捕獲階段。如果不是特別需要,不建議在事件捕獲階段注冊事件處理程序。
** (4)IE事件處理程序 **
attachEvent( 事件名稱,事件函數 ); //添加事件處理程序
detachEvent( 事件名稱,事件函數 ); //移除事件處理程序
由于 IE8 及更早版本只支持事件冒泡,所以通過attachEvent() 添加的事件處理程序都會被添加到冒泡階段。
注:例如 添加點擊事件,attachEvent() 的第一個參數是 "onclick",而非 DOM 的 addEventListener() 方法中的"click" 。
??在 IE 中使用 attachEvent() 與使用 DOM0 級方法的主要區別在于事件處理程序的作用域。在使用DOM0 級方法的情況下,事件處理程序會在其所屬元素的作用域內運行;在使用 attachEvent() 方法的情況下,事件處理程序會在全局作用域中運行,因此 this 等于 window 。
??attachEvent()也可以用來為一個元素添加多個事件處理程序。不過,與 DOM方法不同的是,這些事件處理程序不是以添加它們的順序執行,而是以相反的順序被觸發。例如:下面的例子,點擊按鈕,首先看到的是"Hello world!",然后是"Clicked”。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
alert("Clicked");
});
btn.attachEvent("onclick", function(){
alert("Hello world!");
});
** (5)跨瀏覽器的事件處理程序 **
??首先要創建的方法是 addHandler() ,它的職責是視情況分別使用 DOM0 級方法、DOM2 級方法或 IE 方法來添加事件。這個方法屬于一個名叫 EventUtil 的對象。
??addHandler() 方法接受 3 個參數:要操作的元素、事件名稱和事件函數。
var EventUtil={
addHandler:function(element,type,handler){ //添加事件
if(element.addEventListener){
element.addEventListener(type,handler,false); //使用DOM2級方法添加事件
}else if(element.attachEvent){ //使用IE方法添加事件
element.attachEvent("on"+type,handler);
}else{
element["on"+type]=handler; //使用DOM0級方法添加事件
}
},
removeHandler:function(element,type,handler){ //取消事件
if(element.removeEventListener){
element.removeEventListener(type,handler,false);
}else if(element.detachEvent){
element.detachEvent("on"+type,handler);
}else{
element["on"+type]=null;
}
}
}
使用 EventUtil 對象
var btn = document.getElementById("myBtn");
var handler = function(){
alert("Clicked");
};
EventUtil.addHandler(btn, "click", handler);
EventUtil.removeHandler(btn, "click", handler);