理解JavaScript中的事件流
當瀏覽器發展到第四代時(IE4和Netscape Communicator 4),瀏覽器團隊遇到一個很有意思的問題:頁面的哪一部分會擁有特定的事件?想象下在一張紙上有一組同心圓,如果你把手指放在圓心上,那么你的手指指向的 不是一個圓,而是一組圓。兩家公司的開發團隊在看待瀏覽器事件方面還是一致的。如果你單擊了某個按鈕,那么同時你也單擊了按鈕的容器元素,甚至整個頁面。
事件流描述的是從頁面中接受事件的順序。但有意思的是,IE和Netscape開發團隊居然提出了兩個截然相反的事件流概念。IE的事件流是事件冒泡流,而Netscape的事件流是事件捕獲流。
事件冒泡
IE的事件流叫做事件冒泡,即事件開始時由最具體的元素接受,然后逐級向上傳播到較為不具體的節點。看下面的例子
點擊按鈕,那么這個click事件會按照這樣傳播:
<input>
<div>
<body>
<html>
document
所有現代瀏覽器都支持事件冒泡,但在具體實現上有一些差別。IE5.5及更早版本中的事件冒泡會跳過<html>元素 (從<body>直接跳到document)。IE9、Firefox、Chrome和Safari則將事件一直冒泡到window對象。
事件捕獲
Netscape團隊提出的另一種事件流叫做事件捕獲。事件捕獲的思想是不太具體的DOM節點應該更早接收到事件,而最具體的節點應該最后接收到事件。
針對上面同樣的例子,點擊按鈕,那么此時click事件會按照這樣傳播:
document
<html>
<body>
<div>
<input>
雖然事件捕獲是Netscape唯一支持的事件流模型,但IE9、Safari、Chrome、Opera和Firefox目前也都支持這種事件流模型。但由于老版本的瀏覽器不支持,因此很少有人使用事件捕獲。
DOM事件流
"DOM2級事件"規定的事件流包括三個階段:事件捕獲階段、處于目標階段、事件冒泡階段。首先發生的事件捕獲,為截獲事件提供機會。然后是實際的目標接受事件。最后一個階段是時間冒泡階段,可以在這個階段對事件做出響應。以前面的例子,則會按下圖順序觸發事件。
在DOM事件流中,事件的目標在捕獲階段不會接受到事件。這意味著在捕獲階段,事件從document到div后就定停止了。下一個階段是 處于目標階段,于是事件在input上發生,并在事件處理中被看成冒泡階段的一部分。然后,冒泡階段發生,事件又傳播回document。
多數支持DOM事件流的瀏覽器都實現了一種特定的行為;即使“DOM2級事件”規范明確要求捕獲階段不會涉及事件目標,但IE9、 Safari、Chrome、Firefox和Opera9.5及更高版本都會在捕獲階段觸發事件對象上的事件。結果,就是有兩個機會在目標對象上操作事 件。 看如下例子。
這個Demo的結果,應該很清楚了吧。
來自:http://my.oschina.net/sevenhdu/blog/332014