事件流描述的是從頁面中接收事件的順序。說白了,我做了一件事,這件事怎麼被別人知道的,這個順序就是事件流。 但是對於這個順序,有些人產生了分歧。IE和Netscape提出了幾乎是完全相反的事件流的概念。於是有了(IE)事件冒泡流和(Netscape)事件捕獲流。
事件冒泡
事件冒泡:事件開始時由最具體的元素(文件中巢狀層次最深的那個節點)接收,然後逐級向上傳播到較為不具體的節點(文件)。 如下示例:
<!DOCTYPE html>
<html>
<head>
<title>事件冒泡</title>
</head>
<body>
<div id="myDiv">點我</div>
</body>
</html>
複製程式碼
如果你點選了裡面的<div>
元素,那麼click事件就會按照下面的順序傳播執行:
<div>
<body>
<html>
document
click事件會首先在<div>
元素身上發生,這個元素就是我們點選的的元素,然後才是上一層元素,一直到document元素。
事件捕獲
事件捕獲:不太具體的節點應該更早接收事件,而最具體的節點應該是最後接收到事件。那麼點選<div>
元素就會以下列順序執行click事件:
document
<html>
<body>
<div>
事件捕獲過程,document物件首先接收到click事件,然後依次向下,傳播到事件的實際目標。
DOM事件流
事件流規定包含三個流程:事件捕獲階段,事件冒泡階段和處於目標階段。首先發生是事件捕獲(截獲事件),然後是處於目標階段接收到事件,最後是事件冒泡階段(對事件作出相應)。
在DOM事件流中,目標元素<div>
在事件捕獲階段是不會接受到事件的,下一階段“處於目標階段”,事件在<div>
上發生,並在事件處理中被看成冒泡階段的一部分,然後,冒泡階段發生,事件傳播迴文件。
如何用事件流
在上文中的事件處理,就是我們使用事件流的一種方法,事件是使用者或者瀏覽器自身執行的某種動作,例如'click'、'mouseover'等都是事件的名字,而相應這種操作的函式就叫事件處理程式(事件偵聽)。
-
DOM0級處理事件程式
通過JavaScript指定事件處理程式的傳統方法,就是將一個函式賦值給一個事件處理程式屬性。每個元素(包括window和document)都有自己的事件處理程式屬性,這些屬性全部小寫。如下:
var button = document.getElementById('myButton') button.onclick = function(){ alert('hello'+this.id) } 複製程式碼
我們通過文件物件獲取到一個button的引用,並給它了一個onclick的事件處理程式。但是需要注意的是:如果這段程式碼執行在button的後面,可能會出現你怎麼點選都沒有反應。
DOM0級方法指定的事件處理程式被認為是元素的方法。因此,這個時候的事件處理程式是在該元素的作用域中執行。所以程式碼塊裡面會alert出‘myButton’,往大了說,在這個事件處理程式的作用域中,可以用this訪問到該元素的任何方法和屬性。這種方式新增的事件處理程式會在事件流的冒泡階段被處理。
如果想要刪除這個DOM0級事件處理程式,如下:
button.onclick = null 複製程式碼
再點選就不會有任何反應。
-
DOM2級事件處理程式
DOM2級事件處理程式定義了兩個方法:‘addEventListener()’和‘removeEventListener()’,所有DOM節點都包含這兩個方法,並且它們接收3個引數:要處理的事件名、事件處理的函式、一個布林值。
- 布林值為true,表示在事件捕獲階段執行事件處理程式
- 布林值為false,表示在事件冒泡階段執行事件處理程式
- 如果不寫布林值,預設為false 示例:
var button = document.getElementById('myButton') button.addEventListener('click', function(){ alert('hello'+this.id) }, false) 複製程式碼
和DOM0級事件處理程式一樣,這個this.id列印還是‘myButton’,其作用域仍然在依附的元素中。使用DOM2級事件處理程式的好處是可以新增多個事件,那麼事件就會按照新增它們的順序執行。
通過addEventListener()新增的時間處理程式,只能通過removeEventListener()來刪除。
button.removeEventListener('click', function(){ alert('hello'+this.id) }, false) 複製程式碼
上面這樣做是沒有用的,因為removeEventListener(),需要傳入一樣的引數,表面上你確實引數傳的一樣,其實不然,裡面有個匿名函式,所以你的第二引數永遠都不會一樣。
var button = document.getElementById('myButton') var pomelo = function(){ alert('hello'+this.id) } button.addEventListener('click', pomelo, false) button.removeEventListener('click', pomelo, false) 複製程式碼
上面這樣才是真正的刪除了。
大多數情況下,都是將事件處理程式新增到事件流的冒泡階段,如果不是特別的需求,建議新增到冒泡階段。