React 源碼解析 - Fiber/Reconcile 系列:Fiber 與 Diff

React 源碼解析 - Fiber/Reconcile 系列:Fiber 與 Diff

  • 前言
  • 正文
    • 從 DOM 到 Fiber 對象
      • DOM
      • VDOM
      • React 元素(React Element)
      • Fiber 對象
        • Side Effects
        • Effects list
    • React 架構
    • 關於 Reconciler
      • Stack Reconciler
      • Fiber Reconciler
    • 深入 Reconciliation 工作流程
      • 找出兩棵 React element tree 差異
        • 三大策略
        • React Diff 算法具體過程
          • 對比不同 type 的 react element
          • 對比相同 type 的 react element(Composite Component / Host Component)
          • 同級只有一個節點
          • 同級有多個節點
            • 第一輪遍歷
            • 第二輪遍歷
        • React Diff 算法 Example 1
        • React Diff 算法 Example 2
      • 更新差異到真實 DOM,更新 UI
  • 結語
  • 源碼查看
  • 參考

前言

React Fiber 這個東西一直都聽著,感覺好牛的一個東西,但是感覺好難入門,感到非常難受。先前情提要一下,React Fiber 是 React v16.x 推出的新的架構,而本文的另一個主角 Reconcilation 是 React 的 diff 算法,這兩個東西都是 react 中超級重要的東西!

本文就要來研究下 React Fiber 與 Reconcilation,來看看 fiber 到底是什麼東西?並且 reconcilation 跟 fiber 又是什麼關係,怎麼工作的?而由於是 react 非常核心的機制,所以多會涉及到很多的概念。這篇估計會蠻長的,希望自己可以堅持寫完學習完,想看的也斟酌下。

正文

廢話不多說,首先就先來了解 fiber 到底是什麼吧~

從 DOM 到 Fiber 對象

畢竟 fiber 不是一個那麼簡單的東西,所以我們先從一些基本概念看起,來看看 dom, vdom, react 元素, fiber 對象之間的關係吧~

DOM

文檔對象模型,實際上就是一個樹,樹中的每一個節點就是 HTML 元素(Element),每個節點實際上是一個 JS 對象,這個對象除了包含了該元素的一些屬性,還提供了一些接口(方法),以便編程語言可以插入和操作 DOM。但是 DOM 本身並沒有針對動態 UI 的 Web 應用程序進行太多的支持和優化。因此,當一個頁面有很多元素需要更新時,直接通過 document 更新相對應的 DOM 會使得程序變得很慢,因為瀏覽器需要重新渲染所有的樣式和 HTML。

VDOM

為了優化 “真實” DOM 的更新,出現了 「Virtual DOM」的概念。本質來說,Virtual DOM 是真實 DOM 的模擬,它實際上也是一棵樹。真實的 DOM 樹由真實的 DOM 元素組成,而 Virtual DOM 樹是由 Virtual DOM 元素組成。

當 React 組件的狀態發生變化時,會產生一棵新的 Virtual DOM 樹,然後 React 會使用 diff 算法去比較新、舊兩棵 Virtual DOM 樹,得到其中的差異,然後將「差異」更新到真實的 DOM 樹中,從而完成 UI 的更新。

要說明一點是:這裏並不是說使用了 Virtual DOM 就可以加快 DOM 的操作速度,而是說 React 讓頁面在不同狀態之間變化時,使用了次數盡量少的 DOM 操作來完成。

React 元素(React Element)

在 react 中,react 給 vdom 元素取名叫做 react element,也就是說 react 中的 vdom 是由一堆 react element 構成的,每個節點都是 react 元素。

其實之前就寫過一篇關於 react element 的源碼分析,不過在這邊再複習一遍:

我們來看看源碼中關於 react element 的定義:

/package/shared/ReactElementType.js

export type ReactElement = {
     |
  $$typeof: any,
  type: any,
  key: any,
  ref: any,
  props: any,
  // ReactFiber
  _owner: any,
  ...
|};
  • $$typeof:React 元素的標誌,是一個 Symbol 類型

  • type:React 元素的類型。如果是自定義組件(composite component),那麽 type 字段的值就是一個 class 或 function component;如果是原生 HTML,如 div、span 等,那麽 type 的值就是一個字符串(‘div’、‘span’)

  • key:是 react 元素的 key,在執行 diff 算法的時候會用到

  • ref:React 元素的 ref 屬性,當 React 元素變成真實的 DOM 之後,會返回真實的 DOM 節點引用

  • props:React 元素的屬性,是一個 js 對象

  • _owner: 負責創建這個 React 元素的組件,另外從代碼中的註釋 “// ReactFiber” 可以知道,它裏面包含了 React 元素關聯的 fiber 對象實例,不懂沒關係,下面還會繼續講到 fiber

當我們寫 react 組件時,不論是 class 組件還是 function 組件,這個我們寫的 jsx 都會經過一個 jsx compiler 進行編譯,而其中就會調用 createElement 這個方法。

關於 React.createElement 這個方法,我寫過一篇比較詳細的,有興趣的歡迎去看看 React 源碼解析 - API 系列 - React.createElement/ReactElement,這邊我就簡單說一下。

(下面的一些圖示感謝百度上前端大老們的分享)。

調用 React.createElement 時,實際上就是會為我們創建出來一個 react 元素。

React 源碼解析 - Fiber/Reconcile 系列:Fiber 與 Diff_第1张图片

在上面 ClickCounter 組件這個例子中,

你可能感兴趣的:(React,react,fiber,reconcile,diff)