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