React Fiber 原理

zjy4fun發表於2024-10-07

React Fiber

在 React 16 之前的版本對比更新 VirtualDOM 的過程是採用 Stack 架構實現的,也就是迴圈加遞迴,這種方式的問題是一旦任務開始進行就無法被中斷。

如果應用中的元件數量龐大, Virtual DOM 的層級比較深,主執行緒被長期佔用,知道整顆 Virtual DOM 樹比對更新完成之後主執行緒才能被釋放,主執行緒才能執行其他的任務,這會導致一些使用者互動,動畫等任務無法得到立即執行,頁面會卡頓,非常影響使用者體驗。

核心問題是:遞迴無法被中斷,執行任務耗時長,JavaScript 是單執行緒的,和 Native GUI 互斥,比較 VirtualDOM 的過程中無法執行其他任務,導致任務延遲頁面卡頓,使用者體驗差。

Fiber 的思路

  1. 放棄遞迴呼叫,採用迴圈模擬遞迴,因為迴圈可以被隨時中斷
  2. Fiber 將大的渲染任務拆分成一個個小任務(Fiber節點的建立)
  3. React 使用 window.requestIdleCallback 去利用瀏覽器的空閒時間去執行小任務,React 在執行一個任務單元后,檢視是否有其他高優先順序的任務,如果有,放棄佔用執行緒,先執行優先順序高的任務

關於 window.requestIdleCallback 的作用,可以檢視 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback ,例子可以檢視 https://github.com/zjy4fun/requestIdleCallback

Fiber 的結構

// 簡易版 Fiber 物件
type Fiber = {
  // 元件型別 div、span、元件建構函式
  type: any,
  // DOM 物件
  stateNode: any,  
  // 指向自己的父級 Fiber 物件
  return: Fiber | null,
  // 指向自己的第一個子級 Fiber 物件
  child: Fiber | null,
  // 指向自己的下一個兄弟 iber 物件
  sibling: Fiber | null,
}

Fiber 兩階段

Render

構建 Fiber 物件,構建連結串列,在連結串列中標記要執行的 DOM 操作 ,可中斷。

Commit

根據構建好的連結串列進行 DOM 操作,不可中斷。

參考

https://juejin.cn/post/6993973502852202503

相關文章