摘要:問題如果一個元素和它的祖先元素注冊了同一類型的事件函數例如點擊等那么當事件發生時事件函數調用的順序是什么呢比如考慮如下嵌套的元素
問題
如果一個元素和它的祖先元素注冊了同一類型的事件函數(例如點擊等), 那么當事件發生時事件函數調用的順序是什么呢?
比如, 考慮如下嵌套的元素:
----------------------------------- | outer | | ------------------------- | | |inner | | | ------------------------- | | | -----------------------------------
兩個元素都有onclick的處理函數. 如果用戶點擊了inner, inner和outer上的事件處理函數都會被調用. 但誰先誰后呢?
兩個模型在剛剛過去的那些糟糕年代, Netscape和M$對此有不同的看法.
Netscape認為outer上的處理函數應該先被執行. 這被稱作event capturing.
M$則認為inner上的處理函數具有執行優先權. 這被叫做event bubbling.
兩種看法針鋒相對
事件捕獲(event capturing)當使用事件捕獲時
| | ---------------| |----------------- | outer | | | | -----------| |----------- | | |inner / | | | ------------------------- | | Event CAPTURING | -----------------------------------
outer上的事件處理器先觸發, 然后是inner上的
事件冒泡(event bubbling)/ ---------------| |----------------- | outer | | | | -----------| |----------- | | |inner | | | | | ------------------------- | | Event BUBBLING | -----------------------------------
與事件捕獲相反, 當使用事件冒泡時, inner上的事件處理器先被觸發, 其后是outer上面的
W3C 模型W3C標準則取其折中方案. W3C事件模型中發生的任何事件, 先(從其祖先元素window)開始一路向下捕獲, 直到達到目標元素, 其后再次從目標元素開始冒泡.
1. 先從上往下捕獲 | | | / -----------------| |--| |----------------- | outer | | | | | | -------------| |--| |----------- | | | inner / | | | | | | | | | | | 2. 到達目標元素后從下往上冒泡| | | -------------------------------- | | W3C event model | ------------------------------------------
而你作為開發者, 可以決定事件處理器是注冊在捕獲或者是冒泡階段. 如果addEventListener的最后一個參數是true, 那么處理函數將在捕獲階段被觸發; 否則(false), 會在冒泡階段被觸發.
例如如下的代碼:
var selector = document.querySelector.bind(document); selector("div.outer").addEventListener("click", (e) => { selector("p:first-of-type").textContent += "outer clicked! " }, true) selector("div.inner").addEventListener("click", (e) => { selector("p:first-of-type").textContent += "inner clicked! " }, false) document.addEventListener("click", (e) => { selector("p:first-of-type").textContent += "document clicked! " }, true)
當點擊inner元素時, 如下事情發生了:
點擊事件開始于捕獲階段. 在此階段, 瀏覽器會在inner的所有祖先元素上查找點擊事件處理函數(從window開始).
結果找到了2個, 分別在document和outer上面, 而且這兩個事件處理函數的useCapture選項為true, 說明它們是被注冊在捕獲階段的. 于是, document和outer的點擊處理函數被執行了.
繼續向下尋找, 直到達到inner元素本身. 捕獲階段就此結束. 此時進入冒泡階段, inner上的事件處理器得到執行.
事件命中目標元素后開始向上冒泡, 一路查找是否有注冊了冒泡階段的祖先元素上的事件處理器. 由于沒有找到, 因此什么也沒發生.
最后的結果是:
如果我們把祖先元素的事件處理器注冊在冒泡階段的話(addEventListener的useCapture選項為false):
var selector = document.querySelector.bind(document); selector("div.outer").addEventListener("click", (e) => { selector("p:first-of-type").textContent += "outer clicked! " console.log(e); }, false) selector("div.inner").addEventListener("click", (e) => { selector("p:first-of-type").textContent += "inner clicked! " console.log(e); }, false) document.addEventListener("click", (e) => { selector("p:first-of-type").textContent += "document clicked! " }, false)
結果則是:
傳統模型element.onclick = function(){}
將被注冊在冒泡階段.
事件冒泡的應用例如: 當點擊時的默認函數
如果在document上注冊一個點擊函數:
document.addEventlistener("click", (e) => {}, false)
那么任何元素上的點擊事件最后都會冒泡到這個事件處理器上并觸發函數 - 除非前面的事件處理函數阻止了冒泡(e.stopPropogation(), 在這種情況下事件不會繼續向上冒泡)
注意: e.stopPropagation()只能阻止事件在冒泡階段的向上傳播. 如果被點擊元素的祖先元素有注冊在捕獲階段的事件處理器:
ancestorElem.addEventListner("click", (e) => { // do something... }, true)
那么該祖先元素上的事件處理器照樣會在捕獲階段被觸發.
因此, 你可以在document上設置這么一個處理函數, 當頁面上的任何元素被點擊時, 這個處理函數就被會觸發. 一個實用的例子就是下拉菜單: 當點擊文檔上除下拉菜單本身時任意一處時, 下拉菜單會被隱藏.
在冒泡或者捕獲階段, e.currentTarget指向當前事件處理函數所附著的元素. 你也可以用事件處理函數內的this取而代之.
M$模型的麻煩在M$模型中, 沒有對e.currentTarget的支持, 更糟糕的是, this也不指向當前的HTML元素.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91135.html
摘要:問題如果一個元素和它的祖先元素注冊了同一類型的事件函數例如點擊等那么當事件發生時事件函數調用的順序是什么呢比如考慮如下嵌套的元素 問題 如果一個元素和它的祖先元素注冊了同一類型的事件函數(例如點擊等), 那么當事件發生時事件函數調用的順序是什么呢? 比如, 考慮如下嵌套的元素: ----------------------------------- | outer ...
摘要:事件冒泡與事件捕獲事件冒泡和事件捕獲分別由微軟和網景公司提出,這兩個概念都是為了解決頁面中事件流事件發生順序的問題。事件冒泡微軟提出了名為事件冒泡的事件流。 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網景公司提出,這兩個概念都是為了解決頁面中事件流(事件發生順序)的問題。考慮下面這段代碼,就不寫html->head,body之類的代碼了,自行腦補 Click me! ...
摘要:在之前是只支持事件冒泡,包括之后和目前主流的瀏覽器都同時支持兩種事件。中可以用來取消事件冒泡。 剛接觸 JS 的那個時候,啥也不懂,只想著如何利用 Google、百度到的函數來解決實際的問題,不會想到去一探究竟。 漸漸的,對 JS 的語言的不斷深入,有機會去了解一些原理性東西。最近在看 JQuery 源碼,感觸很多,總想著用原生的 JS 去實現自己的一個 JQuery 庫。說實在的,J...
摘要:事件冒泡與事件捕獲事件冒泡和事件捕獲分別由微軟和網景公司提出,這兩個概念都是為了解決頁面中事件流事件發生順序的問題。如下假設三層都有事件監聽,這時我們點擊的小的藍方框,事件執行的順序是怎么樣的呢紅黃藍事件冒泡微軟提出了名為事件冒泡的事件流。 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網景公司提出,這兩個概念都是為了解決頁面中事件流(事件發生順序)的問題。 如下:假設三層div都...
閱讀 2874·2021-11-24 09:38
閱讀 3511·2021-11-23 09:51
閱讀 967·2021-09-09 11:52
閱讀 4032·2021-08-11 11:18
閱讀 1106·2019-08-30 14:05
閱讀 3228·2019-08-30 11:23
閱讀 1760·2019-08-29 17:02
閱讀 1123·2019-08-26 13:49