js事件流、事件處理程序/事件偵聽器

一、事件流javascript

事件冒泡html

IE的事件流叫作事件冒泡(event bubbling),即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節點)接收,而後逐級向上傳播到較爲不具體的節點(文檔)。java

事件捕獲瀏覽器

事件捕獲的思想是不太具體的節點應該更早的接收到事件,而最具體的節點應該在最後接收到節點。事件捕獲的用意在於事件到達預約目標以前捕獲它。函數

DOM事件流this

「DOM2級事件流」規定的事件流包括三個階段:事件捕獲階段、處於目標階段和冒泡階段。首先發生的是事件捕獲,爲截獲事件提供了機會。而後是實際的目標接收到事件。最後一個階段是冒泡階段,能夠在這個階段對事件做出響應。以簡單的HTML頁面爲例,單擊<div>元素會按照下圖順序觸發事件spa

 

 DOM事件流

在DOM事件流中,實際的目標(<div>元素)在捕獲階段不會接收到事件。這意味着在捕獲階段,事件從document到<html>再到<body>後就中止了。下一個階段是「處於目標」階段,因而事件在<div>上發生,並在事件處理中被當作冒泡階段的一部分。而後冒泡階段發生,事件又傳播迴文檔。code

多數支持DOM事件流的瀏覽器都實現了一種特定行爲;即便「DOM2級事件」規範明確要求捕獲階段不會涉及事件的目標,但Safari、Chrome、Firefox和Opera9.5及更高版本都會在捕獲階段觸發事件對象上的事件。結果,就是有兩個機會在目標對象上面操做事件。htm

Opera、Firefox、Chrome和Safari都支持DOM事件流;IE不支持DOM事件流。對象

 

二、事件處理程序(或事件偵聽器)

事件是用戶或瀏覽器自身執行的某種動做。諸如click、load和mouseover,都是事件的名字。 而響應某個事件的函數就叫作事件處理程序(或事件偵聽器)。事件處理程序的名字以「on」開頭,所以click事件的事件處理程序就是onclick等。爲事件指定處理程序的方式有好幾種。

HTML事件處理程序

某個元素支持的每種事件,均可以使用一個與相應事件處理程序同名的HTML特性指定。如:

<input type="button" value="Click me"  onclick="alert('Clicked')"/>
<script type="text/javascript">
    function showMessage(){
        alert("Hello World!");
    }
</script>
<input type="button" value="Click me"  onclick="showMessage()"/>

在HTML中指定事件有兩個缺點。首先,存在一個時差問題。由於用戶可能在HTML元素一出如今頁面上就觸發相應的事件,但當時事件處理程序有可能尚不具有執行條件。例如前面的例子,假設showMessage函數在按鈕下方頁面最底部定義的,若是用戶在頁面解析showMessage函數以前就單擊了按鈕,就會引起報錯。第二個肯定是HTML與JavaScript代碼緊密耦合。若是要更換事件處理程序,就要改動兩個地方。

DOM0級事件處理程序

經過JavaScript指定事件處理程序的傳統方式,就是講一個函數賦值給一個事件處理程序屬性。要使用JavaScript指定事件處理程序,首先必須取得一個要操做的對象的引用。

每一個元素(包括window和document)都有本身的事件處理程序屬性,這些屬性一般小寫,例如onclick。將這種屬性的值設置成一個函數,就能夠指定事件處理程序。

使用DOM0級方法指定的事件處理程序被認爲是元素的方法,所以是在元素的做用域中運行,換句話說,程序中的this引用當前元素。

var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert(this.id);   //"myBtn"
};

能夠在事件處理程序中經過this訪問元素的任何屬性和方法,以這種方式添加的事件處理程序會在事件流中的冒泡階段被處理。

能夠刪除經過DOM0級方法指定的事件處理程序,只要將事件處理程序屬性的值設爲null便可。

btn.onclick = null;  //刪除事件處理程序

DOM2級事件處理程序

「DOM2級事件」定義了兩個方法,用於處理指定和刪除事件處理程序的操做:addEventListener()和removeEventListener()。全部DOM節點中都包含這兩個方法,而且它們都接受三個參數:要處理的事件名、做爲事件處理程序的函數和一個布爾值。最後這個布爾值若是是true,表示在捕獲階段調用事件處理程序;若是是false,表示在冒泡階段調用事件處理程序。

與DOM0級方法同樣,DOM2級方法天際的事件處理程序也是在其依附的元素的做用域中進行。使用DOM2級方法添加事件處理程序的主要好處是能夠添加多個事件處理程序。來看下面的例子:

btn.addEventListener("click",function(){
    alert(this.id);
},false);
btn.addEventListener("click",function(){
    alert("Hello World!");
},false);

這裏爲按鈕多添加了兩個事件處理程序。這兩個事件處理程序會按照添加它們的順序觸發,所以首先會顯示元素ID,其次會顯示「Hello World!」消息。

經過addEventListener()添加的事件處理程序只能使用removeEventListener來移除;移除時傳入的參數與添加處理程序時使用的參數相同。這也意味着經過addEventListener()添加的匿名函數將沒法移除,以下:

複製代碼
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function(){
    alert(this.id);
},false);
btn.removeEventListener("click",function(){  //沒有用!
    alert(this.id);
},false);
複製代碼
var btn = document.getElementById("myBtn");
var handler = function(){
    alert(this.id);
};
btn.addEventListener("click",handler,false);
btn.removeEventListener("click",handler,false);  //有效!

大多數狀況下,都是將事件處理程序添加到事件流的冒泡階段,這樣能夠最大限度的兼容各類瀏覽器。最好只在須要事件到達目標以前截獲它的時候將事件處理程序添加到捕獲階段。若是不是特別須要,咱們不建議在事件捕獲階段註冊事件處理程序。

Firefox、Safari、Chrome和Opera支持DOM2級事件處理程序

 

IE事件處理程序

IE實現了與DOM相似的兩個方法:attachEvent()和detachEvent()。這兩個方法接受相同的兩個參數:事件處理程序名稱與事件處理程序函數。因爲IE只支持事件冒泡,因此經過attachEvent()添加的事件處理程序都會被添加到冒泡階段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
    alert("Clicked");
});

注意:第一個參數爲「onclick」,而非DOM的addEventListener()方法中的"click"。

在IE中使用attachEvent()與使用DOM0級方法的主要區別在於事件處理程序的做用域。DOM0級事件處理程序會在其所屬元素的做用域內運行;在使用attachEvent()方法的狀況下,事件處理程序會在全局做用域中運行,所以this等於window。在編寫跨瀏覽器的代碼時,牢記這一點區別很是重要。

attachEvent()也能夠爲一個元素添加多個事件處理程序,來看下面的例子:

複製代碼
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
    alert("Clicked");
});
btn.attachEvent("onclick",function(){
    alert("Hello World!");
});
複製代碼

與DOM方法不一樣的是,這些事件處理程序不是以添加它們的順序執行,而是以相反的順序被觸發。單擊這個例子中的按鈕,首先看到的是「Hello World!」,而後纔是「Clicked」。

使用attachEvent()添加的事件能夠經過detachEvent()來移除,條件是必須提供相同的參數。與DOM方法同樣,添加的匿名函數將不能被移除。

var btn = document.getElementById("myBtn");
var handler = function(){
    alert("Clicked");
};
btn.attachEvent("onclick",handler);
btn.detachEvent("onclick",handler); 
相關文章
相關標籤/搜索