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