天天看點

什麼是js的事件流、事件冒泡、事件捕獲以及DOM事件流

了解事件流,我們先來了解“事件”。什麼是事件?在javascript進階程式設計中,有這麼一段話:

javaScript 與HTML 之間的互動是通過事件實作的。事件,就是文檔或浏覽器視窗中發生的一些特定的互動瞬間。可以使用偵聽器(或處理程式)來預訂事件,以便事件發生時執行相應的代碼。這種在傳統軟體工程中被稱為觀察員模式的模型,支援頁面的行為(JavaScript 代碼)與頁面的外觀(HTML 和CSS 代碼)之間的松散耦合。

通俗一點的來說,事件就是“實作使用者點選或者其他形式觸發頁面時,令頁面做出對應改變”。

什麼是事件流?

先來描述一個現象,在紙上畫了很多個同心圓,當用手指指向圓心時,此時你指着的不是一個圓,而是很多個圓。就好像,你在頁面上單擊一個按鈕,這個點選事件不僅僅隻發生在按鈕元素上,同時也發生在按鈕的容器元素上,甚至整個頁面上。

而事件流,描述的是從頁面中接收事件的順序。但IE 和Netscape 開發團隊居然提出了差不多是完全相反的事件流的概念。IE 的事件流是事件冒泡流,而Netscape Communicator 的事件流是事件捕獲流。

事件冒泡

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

<!DOCTYPE html>
<html>
<head>
    <title>Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me</div>
</body>
</html>
           

如果你單擊了頁面中的<div>元素,那麼這個click 事件會按照如下順序傳播:

(1) <div>
(2) <body>
(3) <html>
(4) document
           

也就是說,click 事件首先在<div>元素上發生,而這個元素就是我們單擊的元素。然後,click事件沿DOM樹向上傳播,在每一級節點上都會發生,直至傳播到document 對象。

什麼是js的事件流、事件冒泡、事件捕獲以及DOM事件流

所有現代浏覽器都支援事件冒泡,但在具體實作上還是有一些差别。

事件捕獲

Netscape Communicator 團隊提出的另一種事件流叫做事件捕獲(event capturing)。事件捕獲的思想是不太具體的節點應該更早接收到事件,而最具體的節點應該最後接收到事件。事件捕獲的用意在于在事件到達預定目标之前捕獲它。

<!DOCTYPE html>
<html>
<head>
    <title>Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me</div>
</body>
</html>
           

如果你單擊了頁面中的<div>元素,那麼這個click 事件會按照如下順序傳播:

(1) document
(2) <html>
(3) <body>
(4) <div>
           

在事件捕獲過程中,document 對象首先接收到click 事件,然後事件沿DOM 樹依次向下,一直傳播到事件的實際目标,即<div>元素。

什麼是js的事件流、事件冒泡、事件捕獲以及DOM事件流

雖然事件捕獲是Netscape Communicator 唯一支援的事件流模型,但IE9、Safari、Chrome、Opera和Firefox 目前也都支援這種事件流模型。盡管“DOM2 級事件”規範要求事件應該從document 對象開始傳播,但這些浏覽器都是從window 對象開始捕獲事件的。由于老版本的浏覽器不支援,是以很少有人使用事件捕獲。

DOM事件流

“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處于目标階段和事件冒泡階段。首先發生的是事件捕獲,為截獲事件提供了機會。然後是實際的目标接收到事件。最後一個階段是冒泡階段,可以在這個階段對事件做出響應。

<!DOCTYPE html>
<html>
<head>
    <title>Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me</div>
</body>
</html>
           

如果你單擊了頁面中的<div>元素,那麼這個click 事件會按照如下順序傳播:

什麼是js的事件流、事件冒泡、事件捕獲以及DOM事件流

在DOM 事件流中,實際的目标(<div>元素)在捕獲階段不會接收到事件。這意味着在捕獲階段,事件從document 到<html>再到<body>後就停止了。下一個階段是“處于目标”階段,于是事件在<div>上發生,并在事件處理(後面将會讨論這個概念)中被看成冒泡階段的一部分。然後,冒泡階段發生,事件又傳播回文檔。

IE9、Opera、Firefox、Chrome 和Safari 都支援DOM 事件流;IE8 及更早版本不支援DOM 事件流。

繼續閱讀