理解JavaScript中的事件流

edithfang發表於2014-10-20
當瀏覽器發展到第四代時(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的結果,應該很清楚了吧。
    評論(1)

    相關文章