React 事件系統介紹及源碼分析

舉個例子

你們在使用 React 的過程當中應該都寫過相似這樣的代碼:數組

若是 list 有 1000 項怎麼辦呢?瀏覽器

React 事件系統

幾個關鍵概念

概念 操做 優勢
事件委託 幾乎將全部事件都委託到 document 減小內存佔用和避免頻繁的操做DOM
合成事件 對原生 DOM事件對象的封裝 全部瀏覽器中都表現一致,實現了跨瀏覽器兼容
對象池 利用對象池來管理合成事件對象的建立和銷燬 便於統一管理;能夠減小垃圾回收和新建對象過程當中內存的分配操做,提升了性能
  • 對象池是什麼? 對象池其實就是一個集合,裏面包含了咱們須要的對象集合,這些對象都被對象池所管理,若是須要這樣的對象,從池子裏取出來就行,可是用完須要歸還。緩存

  • 何時使用對象池? 初始化、實例化的代價高,且有需求須要常常實例化,但每次實例化的數量又比較少的狀況下,使用對象池能夠得到顯著的效能提高。異步

大致流程

事件註冊事件觸發事件清理函數

源碼分析

以開頭的例子爲示例代碼進行分析。源碼分析

1.事件註冊性能

咱們寫在 li 元素屬性上的事件監聽函數最終是怎麼綁定到原生 DOM 上的?(如下爲部分節選代碼spa

事件註冊入口

肯定事件最終註冊到哪

  • 利用了事件委託,幾乎全部的事件最終都會被委託到 document 或者 Fragment 上。

獲取原生 DOM 事件名和綁定事件的方式

綁定冒泡階段的事件監聽函數

2.事件觸發3d

點擊 li 元素後,發生了什麼,事件監聽函數是如何被調用的?cdn

事件執行入口

2.1 生成合成事件

從對象池中取出合成事件

  • React 事件系統的一大亮點,它將全部的合成事件都緩存在 對象池 中,能夠大大下降對象的建立和銷燬的時間,提高性能。

模擬捕獲和冒泡

  • 生成合成事件以後,會調用 accumulateTwoPhaseDispatches(event),該方法最終會調用 traverseTwoPhase。

  • 模擬過程當中會把全部事件監聽函數及其對應的節點都加入到 event(合成事件) 的屬性中。

2.2 執行事件

按序執行和清理事件

  • 這也就是爲何當咱們在須要異步讀取操做一個合成事件對象的時候,須要執行 event.persist(),否則 React 就會在這裏釋放掉這個事件。

回調函數真正被執行

  • React 在收集回調數組的時候並不會去管咱們是否調用了 stopPropagation ,而是會在事件執行的階段纔會去檢查是否須要中止冒泡。

3.事件清理 事件執行完以後是如何清理的?

再來舉個🌰

1. 當 React 事件和原生事件混用時的阻止冒泡

  • 在 React 事件系統 中調用 e.stopPropagation() 能夠阻止 React 的合成事件以及綁定在 window 上的原生事件;

  • 在原生事件 中調用 e.stopPropagation(),若是是在 document 以前,那麼全部的 React 事件都會被阻止。

1.點擊 button 以後,輸出結果是什麼?(ABCDE排序)

2.分別把 (1) 和 (2) 的 e.stopPropagation() 加上,輸出結果又是什麼?(ABCDE排序)

2.異步方式訪問事件

有一個模糊搜索框,爲了不頻繁的發送請求,利用 setTimeout 加了 200 毫秒延時。

相關文章
相關標籤/搜索