摘要:事件流是事件冒泡,而的事件流就是事件捕獲。所有現(xiàn)代瀏覽器都支持事件冒泡,并且會將事件一直冒泡到對象。事件捕獲的用以在于事件到達(dá)預(yù)定目標(biāo)之前捕獲它。事件流級事件規(guī)定事件流包括三個階段,事件捕獲階段處于目標(biāo)階段和事件冒泡階段。
最近在復(fù)習(xí)前端的基礎(chǔ),看到事件這一節(jié)的時候,剛好發(fā)現(xiàn)了筆記中一道特別好玩并且十分有趣的代碼,根據(jù)這么一道題目,基本上能夠把事件冒泡和事件捕獲的盲區(qū)給掃空。本文就帶你一起來看看這段有趣的代碼。
但是,首先我們還是要例行公事,把一些基礎(chǔ)的概念過一過,其實也不需要太長的時間。
什么是事件?JavaScript和HTML之間的交互是通過事件實現(xiàn)的。事件,就是文檔或瀏覽器窗口發(fā)生的一些特定的交互瞬間。可以使用監(jiān)聽器(或事件處理程序)來預(yù)定事件,以便事件發(fā)生時執(zhí)行相應(yīng)的代碼。通俗的說,這種模型其實就是一個觀察者模式。(事件是對象主題,而這一個個的監(jiān)聽器就是一個個觀察者)事件流
事件流描述的就是從頁面中接收事件的順序。而IE和Netscape提出了完全相反的事件流概念。IE事件流是事件冒泡,而Netscape的事件流就是事件捕獲。
打個比喻,如果你把手指放在圓心上(多個同心圓),那么你的手指指向的不是一個圓,而是紙上所有的圓。如果你單擊了某個按鈕,在單擊按鈕的同時,也單擊了按鈕的容器元素,甚至是整個頁面。
事件冒泡IE的事件流叫做事件冒泡。即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節(jié)點)接收,然后逐級向上傳播到較為不具體的節(jié)點(文檔)。所有現(xiàn)代瀏覽器都支持事件冒泡,并且會將事件一直冒泡到window對象。事件捕獲
事件捕獲的思想是不太具體的節(jié)點應(yīng)該更早的接收到事件,而在最具體的節(jié)點應(yīng)該最后接收到事件。事件捕獲的用以在于事件到達(dá)預(yù)定目標(biāo)之前捕獲它。IE9+、Safari、Chrome、Opera和Firefox支持,且從window開始捕獲(盡管DOM2級事件規(guī)范要求從document)。由于老版本瀏覽器不支持,所以很少有人使用事件捕獲。DOM事件流
“DOM2級事件”規(guī)定事件流包括三個階段,事件捕獲階段、處于目標(biāo)階段和事件冒泡階段。首先發(fā)生的事件捕獲,為截獲事件提供了機(jī)會。然后是實際的目標(biāo)接收了事件。最后一個階段是冒泡階段,可以在這個階段對事件做出響應(yīng)。
以上這段話,就是我們DOM事件流的根本了,這段話非常重要,雖然看似簡單,但是里面包含著很多小細(xì)節(jié),我會在下面例子中全部講到。
一個十分有趣的例子現(xiàn)在就開始來講解這個有趣的例子,先把代碼貼上來,大致的結(jié)構(gòu)十分簡單。由于segmentfault代碼過長時會有滾動條,這里我把它切分,并省略了一些不必要的結(jié)點,便于觀看。
#a{ width: 300px; height: 300px; background: pink; } #b{ width: 200px; height: 200px; background: blue; } #c{ width: 100px; height: 100px; background: yellow; }
var a = document.getElementById("a"), b = document.getElementById("b"), c = document.getElementById("c"); c.addEventListener("click", function (event) { console.log("c1"); // 注意第三個參數(shù)沒有傳進(jìn) false , 因為默認(rèn)傳進(jìn)來的是 false //,代表冒泡階段調(diào)用,個人認(rèn)為處于目標(biāo)階段也會調(diào)用的 }); c.addEventListener("click", function (event) { console.log("c2"); }, true); b.addEventListener("click", function (event) { console.log("b"); }, true); a.addEventListener("click", function (event) { console.log("a1"); }, true); a.addEventListener("click", function (event) { console.log("a2") }); a.addEventListener("click", function (event) { console.log("a3"); event.stopImmediatePropagation(); }, true); a.addEventListener("click", function (event) { console.log("a4"); }, true);
整個的html頁面就是下面這三個小盒子。
那么現(xiàn)在有三個問題:
如果點擊c或者b,輸出什么?(答案是a1、a3)
stopImmediatePropagation包含了stopPropagation的功能,即阻止事件傳播(捕獲或冒泡),但同時也阻止該元素上后來綁定的事件處理程序被調(diào)用,所以不輸出 a4。因為事件捕獲被攔截了,自然不會觸發(fā) b、c 上的事件,所以不輸出 b、c1、c2,冒泡更談不上了,所以不輸出 a2。
如果點擊a,輸出什么?(答案是 a1、a2、a3)
不應(yīng)該是 a1、a3、a2 嗎?有同學(xué)就會說:“a1、a3可是在捕獲階段被調(diào)用的處理程序的,a2 是在冒泡階段被調(diào)用的啊?!边@正是要說明的:雖然這三個事件處理程序注冊時指定了true、false,但現(xiàn)在事件流是處于目標(biāo)階段,不是冒泡階段、也不是捕獲階段,事件處理程序被調(diào)用的順序是注冊的順序。不論你指定的是true還是false。換句話來說就是現(xiàn)在點擊的是a這個盒子本身,它處于事件流的目標(biāo)狀態(tài),而既非冒泡,又非捕獲。(需要注意的是,此時的eventPhase為2,說明事件流處于目標(biāo)階段。當(dāng)點擊a的時候,先從document捕獲,然后一步步往下找,找到a這個元素的時候,此時的target和currentTarget是一致的,所以認(rèn)定到底了,不需要再捕獲了,此時就按順序執(zhí)行已經(jīng)預(yù)定的事件處理函數(shù),執(zhí)行完畢后再繼續(xù)往上冒泡...)
如果注釋掉event.stopImmediatePropagation,點擊c,會輸出什么?(答案是 a1、a3、a4、b、c1、c2、a2)
如果同一個事件處理程序(指針相同,比如用 handler 保存的事件處理程序),用 addEventListener或 attachEvent綁定多次,如果第三個參數(shù)是相同的話,也只會被調(diào)用一次。當(dāng)然,如果第三個參數(shù)一個設(shè)置為true,另一個設(shè)置為false,那么會被調(diào)用兩次。
而在這里,都是給監(jiān)聽函數(shù)的回調(diào)賦予了一個匿名函數(shù),所以其實每個處理函數(shù)都會被調(diào)用。需要注意的是,如果你還不明白為什么在c上觸發(fā)的先是c1再是c2的話,那么你就需要在去看看第二個問題所描述的內(nèi)容了。
以上,就是本文章的內(nèi)容,文章最后的例子是從網(wǎng)上某個地方看到的,但是具體的出處已經(jīng)忘記了,如果有同學(xué)找到了出處,煩請告知。
參考資料:《JavaScript高級程序設(shè)計》
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/90700.html
摘要:事件流是事件冒泡,而的事件流就是事件捕獲。所有現(xiàn)代瀏覽器都支持事件冒泡,并且會將事件一直冒泡到對象。事件捕獲的用以在于事件到達(dá)預(yù)定目標(biāo)之前捕獲它。事件流級事件規(guī)定事件流包括三個階段,事件捕獲階段處于目標(biāo)階段和事件冒泡階段。 最近在復(fù)習(xí)前端的基礎(chǔ),看到事件這一節(jié)的時候,剛好發(fā)現(xiàn)了筆記中一道特別好玩并且十分有趣的代碼,根據(jù)這么一道題目,基本上能夠把事件冒泡和事件捕獲的盲區(qū)給掃空。本文就帶你...
摘要:事件流是事件冒泡,而的事件流就是事件捕獲。所有現(xiàn)代瀏覽器都支持事件冒泡,并且會將事件一直冒泡到對象。事件捕獲的用以在于事件到達(dá)預(yù)定目標(biāo)之前捕獲它。事件流級事件規(guī)定事件流包括三個階段,事件捕獲階段處于目標(biāo)階段和事件冒泡階段。 最近在復(fù)習(xí)前端的基礎(chǔ),看到事件這一節(jié)的時候,剛好發(fā)現(xiàn)了筆記中一道特別好玩并且十分有趣的代碼,根據(jù)這么一道題目,基本上能夠把事件冒泡和事件捕獲的盲區(qū)給掃空。本文就帶你...
摘要:基礎(chǔ)最后一篇啦,蹭著周六日趕緊寫完,其他的都是的或者瀏覽器能力,高級技巧,使用等雜七雜八的知識點,這里就不一一介紹了,平時編碼也用不太到,有興趣的可以找找相關(guān)的書籍前言先說說事件流吧,事件流就是從從開始到目標(biāo)節(jié)點之前的節(jié)點進(jìn)行事件的捕獲,在 基礎(chǔ)最后一篇啦,蹭著周六日趕緊寫完,其他的都是DOM,BOM的api或者瀏覽器能力,高級技巧,Canvas使用等雜七雜八的知識點,這里就不一一介紹...
摘要:所有節(jié)點中都包含這兩個方法,并且它們都接收個參數(shù)要處理的事件名作為事件處理程序的函數(shù)和一個布爾值。當(dāng)這個布爾值為時,表示在捕獲階段調(diào)用事件處理程序若果是,表示在冒泡階段調(diào)用事件處理程序。 事件流 定義: 1.事件流描述的是從頁面中接收事件的順序,也可理解為事件在頁面中傳播的順序。 2.事件就是用戶或瀏覽器自身執(zhí)行的某種動作。諸如click(點擊)、load(加載)、mouseover(...
摘要:通過管理組件通信通過驅(qū)動視圖比較差異進(jìn)行更新操作作者第七頁鏈接來源知乎著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)。達(dá)到無刷新的效果。對象的狀態(tài)不受外界影響。對象代表一個異步操作,有三種狀態(tài)進(jìn)行中已完成,又稱和已失敗。 以下問題解釋非本人原創(chuàng),是根據(jù)面試經(jīng)驗整理后覺得更容易理解的解釋版本,歡迎補(bǔ)充。 一. 輸入url后的加載過程 從輸入 URL 到頁面加載完成的過程中都發(fā)生了什么 計算機(jī)...
閱讀 1734·2021-11-22 12:09
閱讀 1462·2019-08-30 13:22
閱讀 2094·2019-08-29 17:00
閱讀 2644·2019-08-29 16:28
閱讀 2956·2019-08-26 13:51
閱讀 1183·2019-08-26 13:25
閱讀 3245·2019-08-26 12:14
閱讀 3015·2019-08-26 12:14