摘要:問題如果一個元素和它的祖先元素注冊了同一類型的事件函數(shù)例如點擊等那么當(dāng)事件發(fā)生時事件函數(shù)調(diào)用的順序是什么呢比如考慮如下嵌套的元素
問題
如果一個元素和它的祖先元素注冊了同一類型的事件函數(shù)(例如點擊等), 那么當(dāng)事件發(fā)生時事件函數(shù)調(diào)用的順序是什么呢?
比如, 考慮如下嵌套的元素:
----------------------------------- | outer | | ------------------------- | | |inner | | | ------------------------- | | | -----------------------------------
兩個元素都有onclick的處理函數(shù). 如果用戶點擊了inner, inner和outer上的事件處理函數(shù)都會被調(diào)用. 但誰先誰后呢?
兩個模型在剛剛過去的那些糟糕年代, Netscape和M$對此有不同的看法.
Netscape認為outer上的處理函數(shù)應(yīng)該先被執(zhí)行. 這被稱作event capturing.
M$則認為inner上的處理函數(shù)具有執(zhí)行優(yōu)先權(quán). 這被叫做event bubbling.
兩種看法針鋒相對
事件捕獲(event capturing)當(dāng)使用事件捕獲時
| | ---------------| |----------------- | outer | | | | -----------| |----------- | | |inner / | | | ------------------------- | | Event CAPTURING | -----------------------------------
outer上的事件處理器先觸發(fā), 然后是inner上的
事件冒泡(event bubbling)/ ---------------| |----------------- | outer | | | | -----------| |----------- | | |inner | | | | | ------------------------- | | Event BUBBLING | -----------------------------------
與事件捕獲相反, 當(dāng)使用事件冒泡時, inner上的事件處理器先被觸發(fā), 其后是outer上面的
W3C 模型W3C標準則取其折中方案. W3C事件模型中發(fā)生的任何事件, 先(從其祖先元素window)開始一路向下捕獲, 直到達到目標元素, 其后再次從目標元素開始冒泡.
1. 先從上往下捕獲 | | | / -----------------| |--| |----------------- | outer | | | | | | -------------| |--| |----------- | | | inner / | | | | | | | | | | | 2. 到達目標元素后從下往上冒泡| | | -------------------------------- | | W3C event model | ------------------------------------------
而你作為開發(fā)者, 可以決定事件處理器是注冊在捕獲或者是冒泡階段. 如果addEventListener的最后一個參數(shù)是true, 那么處理函數(shù)將在捕獲階段被觸發(fā); 否則(false), 會在冒泡階段被觸發(fā).
例如如下的代碼:
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)
當(dāng)點擊inner元素時, 如下事情發(fā)生了:
點擊事件開始于捕獲階段. 在此階段, 瀏覽器會在inner的所有祖先元素上查找點擊事件處理函數(shù)(從window開始).
結(jié)果找到了2個, 分別在document和outer上面, 而且這兩個事件處理函數(shù)的useCapture選項為true, 說明它們是被注冊在捕獲階段的. 于是, document和outer的點擊處理函數(shù)被執(zhí)行了.
繼續(xù)向下尋找, 直到達到inner元素本身. 捕獲階段就此結(jié)束. 此時進入冒泡階段, inner上的事件處理器得到執(zhí)行.
事件命中目標元素后開始向上冒泡, 一路查找是否有注冊了冒泡階段的祖先元素上的事件處理器. 由于沒有找到, 因此什么也沒發(fā)生.
最后的結(jié)果是:
如果我們把祖先元素的事件處理器注冊在冒泡階段的話(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)
結(jié)果則是:
傳統(tǒng)模型element.onclick = function(){}
將被注冊在冒泡階段.
事件冒泡的應(yīng)用例如: 當(dāng)點擊時的默認函數(shù)
如果在document上注冊一個點擊函數(shù):
document.addEventlistener("click", (e) => {}, false)
那么任何元素上的點擊事件最后都會冒泡到這個事件處理器上并觸發(fā)函數(shù) - 除非前面的事件處理函數(shù)阻止了冒泡(e.stopPropogation(), 在這種情況下事件不會繼續(xù)向上冒泡)
注意: e.stopPropagation()只能阻止事件在冒泡階段的向上傳播. 如果被點擊元素的祖先元素有注冊在捕獲階段的事件處理器:
ancestorElem.addEventListner("click", (e) => { // do something... }, true)
那么該祖先元素上的事件處理器照樣會在捕獲階段被觸發(fā).
因此, 你可以在document上設(shè)置這么一個處理函數(shù), 當(dāng)頁面上的任何元素被點擊時, 這個處理函數(shù)就被會觸發(fā). 一個實用的例子就是下拉菜單: 當(dāng)點擊文檔上除下拉菜單本身時任意一處時, 下拉菜單會被隱藏.
在冒泡或者捕獲階段, e.currentTarget指向當(dāng)前事件處理函數(shù)所附著的元素. 你也可以用事件處理函數(shù)內(nèi)的this取而代之.
M$模型的麻煩在M$模型中, 沒有對e.currentTarget的支持, 更糟糕的是, this也不指向當(dāng)前的HTML元素.
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/50252.html
摘要:問題如果一個元素和它的祖先元素注冊了同一類型的事件函數(shù)例如點擊等那么當(dāng)事件發(fā)生時事件函數(shù)調(diào)用的順序是什么呢比如考慮如下嵌套的元素 問題 如果一個元素和它的祖先元素注冊了同一類型的事件函數(shù)(例如點擊等), 那么當(dāng)事件發(fā)生時事件函數(shù)調(diào)用的順序是什么呢? 比如, 考慮如下嵌套的元素: ----------------------------------- | outer ...
摘要:事件冒泡與事件捕獲事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出,這兩個概念都是為了解決頁面中事件流事件發(fā)生順序的問題。事件冒泡微軟提出了名為事件冒泡的事件流。 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出,這兩個概念都是為了解決頁面中事件流(事件發(fā)生順序)的問題。考慮下面這段代碼,就不寫html->head,body之類的代碼了,自行腦補 Click me! ...
摘要:在之前是只支持事件冒泡,包括之后和目前主流的瀏覽器都同時支持兩種事件。中可以用來取消事件冒泡。 剛接觸 JS 的那個時候,啥也不懂,只想著如何利用 Google、百度到的函數(shù)來解決實際的問題,不會想到去一探究竟。 漸漸的,對 JS 的語言的不斷深入,有機會去了解一些原理性東西。最近在看 JQuery 源碼,感觸很多,總想著用原生的 JS 去實現(xiàn)自己的一個 JQuery 庫。說實在的,J...
摘要:面試題的基本數(shù)據(jù)類型和引用數(shù)據(jù)類型基本數(shù)據(jù)類型引用數(shù)據(jù)類型和有何區(qū)別表示一個對象被定義了,值為空值表示不存在這個值。 js面試題 JS的基本數(shù)據(jù)類型和引用數(shù)據(jù)類型 基本數(shù)據(jù)類型:undefined、null、boolean、number、string、symbol引用數(shù)據(jù)類型:object、array、function null 和 undefined 有何區(qū)別? null 表示一個對...
摘要:事件冒泡與事件捕獲事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出,這兩個概念都是為了解決頁面中事件流事件發(fā)生順序的問題。如下假設(shè)三層都有事件監(jiān)聽,這時我們點擊的小的藍方框,事件執(zhí)行的順序是怎么樣的呢紅黃藍事件冒泡微軟提出了名為事件冒泡的事件流。 事件冒泡與事件捕獲 事件冒泡和事件捕獲分別由微軟和網(wǎng)景公司提出,這兩個概念都是為了解決頁面中事件流(事件發(fā)生順序)的問題。 如下:假設(shè)三層div都...
閱讀 1084·2021-10-08 10:04
閱讀 3523·2021-08-05 10:01
閱讀 2278·2019-08-30 11:04
閱讀 1794·2019-08-29 15:29
閱讀 836·2019-08-29 15:12
閱讀 1670·2019-08-26 12:11
閱讀 3115·2019-08-26 11:33
閱讀 1163·2019-08-26 10:23