這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)如何進(jìn)行JS中的事件冒泡與捕獲,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶(hù)創(chuàng)新互聯(lián)還提供了石林免費(fèi)建站歡迎大家使用!
剛接觸 JS 的那個(gè)時(shí)候,啥也不懂,只想著如何利用 Google、百度到的函數(shù)來(lái)解決實(shí)際的問(wèn)題,不會(huì)想到去一探究竟。
漸漸的,對(duì) JS 的語(yǔ)言的不斷深入,有機(jī)會(huì)去了解一些原理性東西。最近在看 JQuery 源碼,感觸很多,總想著用原生的 JS 去實(shí)現(xiàn)自己的一個(gè) JQuery 庫(kù)。說(shuō)實(shí)在的,JQuery 里面很多函數(shù)和思路,是千百開(kāi)源工作者長(zhǎng)期的貢獻(xiàn),哪能是短時(shí)間就能消化的了。
最近再次碰到 addEventListener函數(shù)(MDN 上關(guān)于 addEventListener 的介紹,很詳細(xì)),由于之前并沒(méi)有弄懂第三個(gè)參數(shù)的含義,要么默認(rèn)值,要么手動(dòng)設(shè)置成 false。這次看了不少文章,徹底把事件冒泡和捕獲弄懂。
什么事件冒泡與捕獲
事件冒泡與捕獲是 DOM 中事件傳播的兩種方式,比如說(shuō)對(duì)于注冊(cè)了相同事件的兩個(gè) DOM 元素(簡(jiǎn)單點(diǎn)就是兩個(gè) div,一里一外),當(dāng)點(diǎn)擊里層 div 的時(shí)候,這兩個(gè)事件誰(shuí)先執(zhí)行。
冒泡事件,由里向外,最里層的元素先執(zhí)行,然后冒泡到外層。
捕獲事件,由外向里,最外層的元素先執(zhí)行,然后傳遞到內(nèi)部。
在 IE 9 之前是只支持事件冒泡,IE 9(包括 IE 9) 之后和目前主流的瀏覽器都同時(shí)支持兩種事件。
如何設(shè)置,只需修改 addEventListener的第三個(gè)參數(shù),true 為捕獲,false 為冒泡,默認(rèn)為冒泡。
舉個(gè)簡(jiǎn)單的例子,
在上面這個(gè)例子中,事件是按照冒泡來(lái)執(zhí)行的,點(diǎn)擊里層的 in,會(huì)看到先 alert 的順序是先 "in" 后 "out",如果把事件改成捕獲,alert 的順序又不一樣了。
上面這個(gè)例子是捕獲事件的例子,點(diǎn)擊 in效果是不是不一樣呢?
之所以會(huì)有冒泡和捕獲事件(像 IE 9 之前的瀏覽器不支持捕獲事件,還真是反程序員),畢竟在實(shí)際中處理事情肯定有個(gè)先后順序,要么由里向外,要么由外向里,兩者都是必須的。
但有時(shí)候?yàn)榱思嫒?IE 9 以下版本的瀏覽器,都會(huì)把第三個(gè)參數(shù)設(shè)置成 false 或者默認(rèn)(默認(rèn)就是 false)。
進(jìn)一步理解冒泡和捕獲
現(xiàn)在已經(jīng)說(shuō)清楚冒泡和捕獲,那么如果同時(shí)出現(xiàn)冒泡和捕獲會(huì)出現(xiàn)什么結(jié)果?
原來(lái)瀏覽器處理時(shí)間分為兩個(gè)階段,捕獲階段和冒泡階段,
先執(zhí)行捕獲階段,如果事件是在捕獲階段執(zhí)行的(true 情況),則執(zhí)行;
然后是冒泡階段,如果事件是在冒泡階段執(zhí)行的(false 情況),則執(zhí)行;
來(lái)看一看例子就知道了:
s1 s2 s3
這次我們?cè)O(shè)置三個(gè) span,分別是 s1, s2, s3,然后設(shè)置 s1,s3 為冒泡執(zhí)行,s2 為捕獲執(zhí)行:
從運(yùn)行的效果來(lái)看,點(diǎn)擊 s3,依次 alert s2 => s3 => s1,說(shuō)明:
捕獲事件和冒泡事件同時(shí)存在的,而且捕獲事件先執(zhí)行,冒泡事件后執(zhí)行;
如果元素存在事件且事件的執(zhí)行時(shí)間與當(dāng)前邏輯一致(冒泡或捕獲),則執(zhí)行。
默認(rèn)事件取消與停止冒泡
當(dāng)然,有時(shí)候我們只想執(zhí)行最內(nèi)層或最外層的事件,根據(jù)內(nèi)外層關(guān)系來(lái)把范圍更廣的事件取消掉(對(duì)于新手來(lái)說(shuō),不取消冒泡,很容易中招的出現(xiàn) bug)。event.stopPropagation()(IE 中window.event.cancelBubble = true)可以用來(lái)取消事件冒泡。
有時(shí)候?qū)τ跒g覽器的默認(rèn)事件也需要取消,這時(shí)候用到的函數(shù)則是 event.preventDefault()(IE 中window.event.returnValue = false)。
那么默認(rèn)事件取消和停止冒泡有什么區(qū)別呢?我的理解:瀏覽器的默認(rèn)事件是指瀏覽器自己的事件(這不廢話(huà)嗎),比如 a 標(biāo)簽 的點(diǎn)擊,表單的提交等,取消掉就不會(huì)執(zhí)行啦;冒泡則取消的是由外向里(捕獲)、由里向外(冒泡),stop 之后,就不會(huì)繼續(xù)遍歷了。stackoverflow 上的解答
看下例子,依舊是上面那個(gè)例子,不過(guò)每個(gè)函數(shù)都加了 停止冒泡:
s1.addEventListener('click',function(e){ e.stopPropagation(); alert('s1'); },false); s2.addEventListener('click',function(e){ e.stopPropagation(); alert('s2'); },true); s3.addEventListener('click',function(e){ e.stopPropagation(); alert('s3'); },false);
點(diǎn)擊的結(jié)果是:當(dāng)點(diǎn)擊 s2 或 s3 的時(shí)候,都會(huì) alert s2,點(diǎn)擊 s1,彈出 s1。因?yàn)槭录蝗∠木壒剩c(diǎn)擊 s3,執(zhí)行 s2后就不會(huì)在向下執(zhí)行了。
在看一個(gè) preventDefault 的例子。
第二個(gè)鏈接是不是回不了主頁(yè),因?yàn)闉g覽器的默認(rèn)事件被取消了。
總結(jié)就補(bǔ)充兩個(gè)兼容 IE 的函數(shù)吧:
function stopBubble(e) { //如果提供了事件對(duì)象,則這是一個(gè)非IE瀏覽器 if ( e && e.stopPropagation ) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else //否則,我們需要使用IE的方式來(lái)取消事件冒泡 window.event.cancelBubble = true; } //阻止瀏覽器的默認(rèn)行為 function stopDefault( e ) { //阻止默認(rèn)瀏覽器動(dòng)作(W3C) if ( e && e.preventDefault ) e.preventDefault(); //IE中阻止函數(shù)器默認(rèn)動(dòng)作的方式 else window.event.returnValue = false; return false; }
上述就是小編為大家分享的如何進(jìn)行JS中的事件冒泡與捕獲了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。