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