簡(jiǎn)述js事件傳播流程

一、概述

事件流:事件流描述的是從頁(yè)面中接收事件的順序。

DOM事件流傳播的三個(gè)過(guò)程:

事件捕獲階段 ——》 處于目標(biāo)階段 ——》 事件冒泡階段。

事件冒泡:事件開(kāi)始時(shí)由最具體的元素接收,然后逐級(jí)向上傳播到較為不具體的元素

事件捕獲:不太具體的節(jié)點(diǎn)更早接收事件,而最具體的元素最后接收事件,和事件冒泡相反

事件流示意

支持W3C標(biāo)準(zhǔn)的瀏覽器在添加事件時(shí)用addEventListener(event,fn,useCapture)方法,基中第3個(gè)參數(shù)useCapture是一個(gè)Boolean值,用來(lái)設(shè)置事件是在事件捕獲時(shí)執(zhí)行,還是事件冒泡時(shí)執(zhí)行。而不兼容W3C的瀏覽器(IE)用attachEvent()方法,此方法沒(méi)有相關(guān)設(shè)置,不過(guò)IE的事件模型默認(rèn)是在事件冒泡時(shí)執(zhí)行的,也就是在useCapture等于false的時(shí)候執(zhí)行,所以把在處理事件時(shí)把useCapture設(shè)置為false是比較安全,也實(shí)現(xiàn)兼容瀏覽器的效果。

二、示例

假設(shè)一個(gè)元素div,它有一個(gè)下級(jí)元素p。

<div onclick="alert(1)">

<p onclick="alert(2)">元素</p>

</div>
這兩個(gè)元素都綁定了click事件,如果用戶點(diǎn)擊了p,它在div和p上都觸發(fā)了click事件,那這兩個(gè)事件處理程序哪個(gè)先執(zhí)行呢?事件順序是什么?

事件捕獲

當(dāng)你使用事件捕獲時(shí),父級(jí)元素先觸發(fā),子級(jí)元素后觸發(fā),即div先觸發(fā),p后觸發(fā)。

事件冒泡

當(dāng)你使用事件冒泡時(shí),子級(jí)元素先觸發(fā),父級(jí)元素后觸發(fā),即p先觸發(fā),div后觸發(fā)。

W3C模型

W3C模型是將兩者進(jìn)行中和,在W3C模型中,任何事件發(fā)生時(shí),先從頂層開(kāi)始進(jìn)行事件捕獲,直到事件觸發(fā)到達(dá)了事件源元素。然后,再?gòu)氖录赐线M(jìn)行事件冒泡,直到到達(dá)document。

【注】:當(dāng)兩個(gè)元素有包含關(guān)系并且事件相同時(shí)才會(huì)觸發(fā)冒泡和捕獲機(jī)制

另外:

1)、盡管“DOM2級(jí)事件”,即addEventListener(event,fn,useCapture)方法,標(biāo)準(zhǔn)規(guī)范明確規(guī)定事件捕獲階段不會(huì)涉及事件目標(biāo),但是在IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都會(huì)在捕獲階段觸發(fā)事件對(duì)象上的事件。所以結(jié)果就是有兩次機(jī)會(huì)在目標(biāo)對(duì)象上面操作事件。

2)、然而并非所有的事件都會(huì)經(jīng)過(guò)冒泡階段 。所有的事件都要經(jīng)過(guò)捕獲階段和處于目標(biāo)階段,但是有些事件會(huì)跳過(guò)冒泡階段:如,獲得輸入焦點(diǎn)的focus事件和失去輸入焦點(diǎn)的blur事件。

三、阻止事件流

為何阻止事件流:

如我們點(diǎn)擊p標(biāo)簽時(shí)希望只彈出1,但是點(diǎn)p的時(shí)候頁(yè)會(huì)觸發(fā)div上的點(diǎn)擊事件彈出2,這是我們不想要的效果,所以就需要阻止事件流

阻止冒泡

document.getElementsByTagName("p").addEventListener("click",function(event){

console.log("阻止冒泡");???

event.stopPropagation();

},false);

另外:

event.cancelBubble=true;? IE8以下版本瀏覽器支持的阻止事件冒泡方法

上面的event.stopPropagation();是其他瀏覽器支持的阻止事件冒泡方法

阻止捕獲

DOM3級(jí)新增事件stopImmediatePropagation()方法來(lái)阻止事件捕獲,另外此方法還可以阻止事件冒泡

document.getElementsByTagName("p").addEventListener("click",function(){????

console.log("阻止捕獲");????

event.stopImmediatePropagation();

},true);?

stopImmediatePropagation() 和 stopPropagation()的區(qū)別在哪兒呢?

后者只會(huì)阻止冒泡或者是捕獲。 但是前者除此之外還會(huì)阻止該元素的其他事件發(fā)生,但是后者就不會(huì)阻止其他事件的發(fā)生。

注意:在DOM事件流中,實(shí)際的目標(biāo)在捕獲階段不會(huì)接收到事件,下一個(gè)階段是處于目標(biāo)階段,這時(shí)事件被觸發(fā),最后進(jìn)入事件冒泡階段。我們認(rèn)為處于目標(biāo)階段是事件冒泡階段的一部分。


四、兩種事件流模型

1、所有現(xiàn)代瀏覽器都支持事件冒泡,但在具體實(shí)現(xiàn)中略有差別:

IE5.5及更早版本中事件冒泡會(huì)跳過(guò)<html>元素(從body直接跳到document)。

IE9、Firefox、Chrome、和Safari則將事件一直冒泡到window對(duì)象。

2、IE9、Firefox、Chrome、Opera、和Safari都支持事件捕獲。盡管DOM標(biāo)準(zhǔn)要求事件應(yīng)該從document對(duì)象開(kāi)始傳播,但這些瀏覽器都是從window對(duì)象開(kāi)始捕獲事件的。

3、由于老版本瀏覽器不支持,很少有人使用事件捕獲。建議使用事件冒泡。


五、事件代理

傳統(tǒng)的事件處理中,需要為每個(gè)元素添加事件處理器。js事件代理則是一種簡(jiǎn)單有效的技巧,通過(guò)它可以把事件處理器添加到一個(gè)父級(jí)元素上,從而避免把事件處理器添加到多個(gè)子級(jí)元素上。

target、this、currentTarget的區(qū)別

先訴重點(diǎn)理論:

1. target:觸發(fā)事件的某個(gè)具體對(duì)象,只會(huì)出現(xiàn)在事件流的目標(biāo)階段(誰(shuí)觸發(fā)誰(shuí)命中,所以肯定是目標(biāo)階段)

2. currentTarget:綁定事件的對(duì)象,恒等于this,可能出現(xiàn)在事件流的任意一個(gè)階段中

3. 通常情況下terget和currentTarget是一致的,我們只要使用terget即可,但有一種情況必須區(qū)分這三者的關(guān)系,那就是在父子嵌套的關(guān)系中,父元素綁定了事件,單擊了子元素(根據(jù)事件流,在不阻止事件流的前提下他會(huì)傳遞至父元素,導(dǎo)致父元素的事件處理函數(shù)執(zhí)行),這時(shí)候currentTarget指向的是父元素,因?yàn)樗?b>綁定事件的對(duì)象,而target指向了子元素,因?yàn)樗?b>觸發(fā)事件的那個(gè)具體對(duì)象,如下代碼和截圖所示:

<div id="one">

? <div id="three"></div>

</div>

one.addEventListener('click',function(e){

? ? console.log(e.target);? //three

? ? console.log(e.currentTarget);? //one

},false);


target:獲得觸發(fā)事件的標(biāo)簽,currentTarget:得到綁定事件的標(biāo)簽

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的。 ??事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,701評(píng)論 1 11
  • 以下文章為轉(zhuǎn)載,對(duì)理解JavaScript中的事件處理機(jī)制很有幫助,淺顯易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy閱讀 3,173評(píng)論 1 10
  • js之事件機(jī)制 1、事件初探 1.1 js事件的概述 JavaScript事件:JavaScript是基于事件驅(qū)動(dòng)...
    道無(wú)虛閱讀 2,632評(píng)論 0 2
  • 背景知識(shí) 什么是事件?直觀的說(shuō)就是網(wǎng)頁(yè)上發(fā)生的事情,大部分是指用戶的鼠標(biāo)動(dòng)作和鍵盤(pán)動(dòng)作,如點(diǎn)擊、移動(dòng)鼠標(biāo)、按下某個(gè)...
    吧啦啦小湯圓閱讀 1,990評(píng)論 2 15
  • (1)冒泡型事件:事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對(duì)象)的順序觸發(fā)。 (2)捕獲型...
    逍遙g閱讀 481評(píng)論 2 0

友情鏈接更多精彩內(nèi)容