摘要:解決問題為了解決上述問題,先來了解下的事件,事件是合成事件,為原生事件的一個子集,僅僅是進(jìn)行了一個跨瀏覽器的封裝。參考本文部分參考自事件初探
寫在前面
本文源于本人在學(xué)習(xí)react過程中遇到的一個問題;本文內(nèi)容為本人的一些的理解,如有不對的地方,還請大家指出來。本文是講react的事件,不是介紹其api,而是猜想一下react合成事件的實現(xiàn)方式
遇到的問題class EventTest extends Component { handleParentClick(e) { console.log("click parent div"); } handleChildClick(e) { e.stopPropagation(); console.log("click child div"); } componentDidMount() { document.querySelector(".parent").addEventListener("click", this.handleParentClick); } render() { return (); } }
上述代碼render出來后,嘗試點擊一下div.child,詭異的現(xiàn)象產(chǎn)生了:
控制臺中輸出如上圖所示,這完全不符合瀏覽器的事件執(zhí)行啊,我所期望的是指輸出click child div,因為已經(jīng)利用了e.stopPropagation()來阻止冒泡,說明阻止冒泡失效了,但是僅僅如此嗎,可以發(fā)現(xiàn)的是首先輸出的是click parent div(wtf)。
解決問題為了解決上述問題,先來了解下react的事件,react事件是合成事件,為原生事件的一個子集,僅僅是進(jìn)行了一個跨瀏覽器的封裝。但是真的只有這么簡單?圖樣圖森破。
利用控制臺,看下div.child對應(yīng)的事件處理函數(shù):
一個空函數(shù),事件的監(jiān)聽函數(shù)不是所定義的handleChildClick,而是emptyFunction,也就是說react沒有在真實的DOM節(jié)點上綁定事件(在DOM節(jié)點上綁定事件比較消耗內(nèi)存,因為當(dāng)dom節(jié)點被remove后,雖然不存在與dom tree中,但是仍存在與內(nèi)存中,需要手動remove事件orchild = null),react的合成事件利用的是事件代理方式實現(xiàn),也就是說會將事件監(jiān)聽器綁定到整個文檔document上,是不是這樣呢?來驗證一下,利用chrome:
可以發(fā)現(xiàn),document上的確被綁定了click事件,dom節(jié)點的真實的事件處理函數(shù)全部以一個特定的結(jié)構(gòu)存儲在了內(nèi)存中,當(dāng)點擊div.child時,這時其事件處理函數(shù)為emptyFunction,執(zhí)行這個函數(shù)無任何作用,按照瀏覽器標(biāo)準(zhǔn)事件模型,開始向上冒泡,這時到了div.parent,于是輸出了click parent div,一直向上到了document上,這時根據(jù)e.target進(jìn)行處理,而react并不會根據(jù)dom層級式傳播那樣遍歷virtual dom結(jié)構(gòu),這樣有時遍歷的層級會很多,而且會有很多的無效遍歷。
react是怎么做的呢?react依靠每個React component各自獨立的id來編碼這個層級。這樣就能通過簡單的字符串操作來獲取所有父級 component 的父級內(nèi)容,再把事件監(jiān)聽存儲在hashmap當(dāng)中,比如有如下結(jié)構(gòu)并且為沒一層div添加onClick
div.a div.b div.c
當(dāng)點擊div.c時,處理方式:
clickBubbleListeners["a.b.c"](event); clickBubbleListeners["a.b"](event); clickBubbleListeners["a"](event);
在合成事件中用e.stopPropagation只能阻斷上述冒泡過程。
結(jié)論由此可以看出:
阻止react事件冒泡的行為只能用于react合成事件中,對于原生事件無效(合成事件中的e.stopPropagation與原生事件中的e.stopPropagation并不是一回事)
阻止原生事件的冒泡行為,可以阻止react合成事件的傳播(根本不會冒泡到document上,所以不會觸發(fā)react的合成事件)
在寫react時,最好不要將合成事件與原生事件混用。
參考本文部分參考自IMWeb—React事件初探
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/81111.html
摘要:僅對于組件,用于監(jiān)聽原生事件,而不是組件內(nèi)部使用觸發(fā)的事件。注意,你無法對中的賦值,因為已經(jīng)自動為你進(jìn)行了同步。 簡介 在使用Vue進(jìn)行開發(fā)的時候,大多數(shù)情況下都是使用template進(jìn)行開發(fā),使用template簡單、方便、快捷,可是有時候需要特殊的場景使用template就不是很適合。因此為了很好使用render函數(shù),我決定深入窺探一下。各位看官如果覺得下面寫的有不正確之處還望看官...
摘要:而且默認(rèn)帶有執(zhí)行的順序是,,即便是內(nèi)聯(lián)的,依然具有屬性。模塊腳本只會執(zhí)行一次必須符合同源策略模塊腳本在跨域的時候默認(rèn)是不帶的。通常被用作腳本被禁用的回退方案。最后標(biāo)簽真的令人感到興奮。 窺探 Script 標(biāo)簽 0x01 什么是 script 標(biāo)簽? script 標(biāo)簽允許你包含一些動態(tài)腳本或數(shù)據(jù)塊到文檔中,script 標(biāo)簽是非閉合的,你也可以將動態(tài)腳本或數(shù)據(jù)塊當(dāng)做 script 的...
摘要:而且默認(rèn)帶有執(zhí)行的順序是,,即便是內(nèi)聯(lián)的,依然具有屬性。模塊腳本只會執(zhí)行一次必須符合同源策略模塊腳本在跨域的時候默認(rèn)是不帶的。通常被用作腳本被禁用的回退方案。最后標(biāo)簽真的令人感到興奮。 窺探 Script 標(biāo)簽 0x01 什么是 script 標(biāo)簽? script 標(biāo)簽允許你包含一些動態(tài)腳本或數(shù)據(jù)塊到文檔中,script 標(biāo)簽是非閉合的,你也可以將動態(tài)腳本或數(shù)據(jù)塊當(dāng)做 script 的...
摘要:所謂知其然還要知其所以然本文將分析的部分源碼包括組件初始渲染的過程和組件更新的過程在這之前假設(shè)讀者已經(jīng)對有一定了解知道區(qū)別了解生命周期事務(wù)批量更新大致概念等如何分析源碼代碼架構(gòu)預(yù)覽首先我們找到在上的地址把版本的源碼下來觀察它的整體架構(gòu)這 所謂知其然還要知其所以然. 本文將分析 React 15-stable的部分源碼, 包括組件初始渲染的過程和組件更新的過程.在這之前, 假設(shè)讀者已經(jīng):...
摘要:主要兼容的微信的瀏覽器,因為要在朋友圈來營銷,總體來說,會偏設(shè)計以及動畫些。 有一天,我們組內(nèi)的一個小伙伴突然問我,你知道有一個叫重構(gòu)工程師的崗位?這是干什么的?重構(gòu)工程師 這個問題引發(fā)了我對前端領(lǐng)域發(fā)展的思考,所以我來梳理下前端領(lǐng)域的發(fā)展過程,順便小小的預(yù)測下2017年的趨勢。不想看回憶的,可以直接跳到后面看展望。 神說,要有光,就有了光 自1991年蒂姆·伯納斯-李公開提及HTML...
閱讀 662·2021-11-24 09:39
閱讀 3507·2019-08-30 15:53
閱讀 2545·2019-08-30 15:44
閱讀 3262·2019-08-30 12:54
閱讀 2234·2019-08-29 12:23
閱讀 3330·2019-08-26 14:05
閱讀 2131·2019-08-26 13:36
閱讀 3462·2019-08-26 13:33