React 核心原理與Fiber架構

目錄

一、虛擬 DOM

二、Diffing 算法

三、Fiber 架構

四、渲染流程

1. Render 階段(可中斷異步過程)

2. Commit 階段(同步不可中斷)

五、時間切片(Time Slicing)

六、核心流程步驟總結

1. 狀態更新觸發

2. Render 階段(異步可中斷,構建 Fiber 樹)

3. Commit 階段(同步不可中斷,更新真實 DOM)

4. 雙緩存機制切換

5. 調度系統核心支撐

七、組件觸發渲染的時機


相關內容:?

React Fiber 架構原理:關于 Fiber 樹的一切

React核心原理淺析

二十分鐘掌握React核心理念,老鳥快速入門指南


一、虛擬 DOM

React 使用虛擬 DOM 來表示 UI 的狀態。虛擬 DOM 是一個輕量級的 JavaScript 對象,每個節點包含?tag(標簽名)、props(屬性)、children(子節點)。

核心價值在于性能優化 —— 直接操作真實 DOM 會觸發瀏覽器重排 / 重繪,成本很高;而虛擬 DOM 先在內存中通過 Diff 算法比對狀態變更,再批量更新真實 DOM,減少瀏覽器操作次數。

二、Diffing 算法

Diffing 算法用于比較新舊虛擬 DOM 樹,以最小的操作次數將舊 DOM 樹轉換為新 DOM 樹。

React 提出了復雜度為 O(n) 的啟發式算法,通過設置 key 屬性來標識一組同級子元素,從而高效地更新真實 DOM。

  1. 同層比較(Tree Diff):僅逐層對比節點,不跨層級遍歷。若節點類型不同,直接銷毀整棵子樹及其組件實例并重建。
  2. Key 值優化:列表渲染時需為元素提供唯一?key,用于標識節點身份。通過?key,React 可識別節點的移動或復用,避免全量更新。
  3. 組件類型比對:若組件類型相同,則遞歸更新子節點;若類型不同,則卸載舊組件并掛載新組件。

不指定 key 的后果:

React 通過 ??key + 組件類型?? 的組合來識別元素的身份,沒有 key 時默認使用 ??數組索引?? 作為 key。

若用索引作為 key,當列表項順序變化或中間插入 / 刪除元素時,React 會錯誤地認為大量節點需重新創建,而非移動或更新,導致不必要的 DOM 操作(如重復卸載 / 掛載組件),嚴重影響性能。

索引作為 key 的問題本質:

  • ??綁定問題??:使用索引作為 key 時狀態綁定到??位置??,而非??數據???
  • DOM復用規則??:React 只復用相同 key 對應的 DOM 節點
  • ??數據與DOM分離??:React 更新內容但不更新狀態
  • ??狀態漂移??:輸入狀態留在原位置,被新元素繼承

使用唯一 ID 作為 key 可以解決這個問題,因為它確保狀態與數據項(而非位置)保持一致關聯。


三、Fiber 架構

Fiber 架構解決了傳統同步渲染阻塞主線程的問題,實現可中斷的異步渲染,支持時間切片和優先級調度。

Fiber 節點結構

每個組件對應一個 Fiber 節點,構成鏈表樹(非傳統遞歸樹)。節點包含組件類型、狀態、副作用標記(effectTag,如刪除、新增節點)、節點指針:child(指向第一個子節點)、sibling(指向下一個兄弟節點)、return(指向父節點)。

雙緩存機制

  • Current Tree:當前已渲染到頁面的 Fiber 樹。
  • WorkInProgress Tree:后臺構建的新 Fiber 樹,用于計算變更。

兩棵樹通過?alternate?指針關聯,每次更新時新建?WorkInProgress Tree,構建完成后直接替換Current Tree,保證視圖連續性。


四、渲染流程

1. Render 階段(可中斷異步過程)

構建 Fiber 鏈表樹,通過 Diff 標記副作用(如節點增刪)。

1. 深度優先遍歷
從根節點開始,采用深度優先遍歷,通過?beginWork?向下處理每個 Fiber 節點,逐步構建 Fiber 鏈表樹。

2. Diffing 算法執行
對比新舊子節點,決定復用/移動/刪除,并標記?effectTag(如?Placement?移動節點)。

  • 節點復用條件:父節點已復用,且?key?和?type?相同。
  • 子節點 Diff 順序:先嘗試單節點匹配,再處理多節點末尾增刪(一輪循環),最后處理復雜移動場景(二輪循環),盡可能減少節點移動開銷。

3. 向上回溯
當節點無子節點時,進入?completeUnitOfWork,自底向上收集?effectTag,將子節點的?effectList?合并到父節點,最終形成從根節點到葉節點的副作用鏈表。

4. 中斷與恢復
利用時間切片(Time Slicing)將任務拆分為微任務,在瀏覽器空閑時執行,避免阻塞主線程。每處理完一個節點,檢查剩余時間片,時間耗盡時暫停,通過全局變量保存進度,瀏覽器空閑時通過調度器恢復任務。

2. Commit 階段(同步不可中斷)

批量執行副作用,更新真實 DOM。此階段必須一氣呵成,確保 DOM 操作的原子性。

遍歷?effectList,批量更新真實 DOM(執行?effectTag?對應的操作,如創建、刪除節點)。觸發回調,處理 ref 和 useEffect。


五、時間切片(Time Slicing)

時間切片策略將渲染任務拆分為微任務單元,利用瀏覽器空閑時段執行,提升響應性。

調度器:模擬?requestIdleCallback?功能(兼容舊瀏覽器),設置任務優先級,通過?MessageChannel?實現異步調度,將任務拆分為小單元,每次執行完一個單元后,檢查是否有高優先級任務插隊,若有則暫停當前任務。

任務優先級:分為五級(緊急交互 > 過渡動畫 > 普通更新 > 延遲更新 > 過期任務),高優先級任務可插隊執行,中斷低優先級任務;低優先級任務可暫停或丟棄,避免占用主線程。例如,用戶點擊按鈕時,渲染任務會被暫停,優先處理點擊回調。

調度系統通過四層架構實現:

  1. SchedulerHostConfig:對接瀏覽器底層能力,利用?MessageChannel?計算空閑時間,提供空閑回調機制,是 Fiber 調度的基礎。
  2. Scheduler:核心任務管理模塊,定義五級優先級,通過雙向循環鏈表維護任務池,實現任務的注冊、取消和優先級排序,并在瀏覽器空閑時執行任務。
  3. SchedulerWithReactIntegration:抹平調度接口,將 Scheduler 與 React 的更新流程整合,例如在狀態更新時觸發調度。
  4. ReactFiberScheduler:應用層調度入口,將 React 的更新任務(如 Fiber 樹的構建)包裝為 Scheduler 可處理的任務,在 Render 階段通過?shouldYield()?檢查是否需要中斷任務,確保主線程不阻塞。

六、核心流程步驟總結

1. 狀態更新觸發

  • 因用戶交互(如點擊)、setState?或 Hooks 更新函數調用,觸發組件狀態變更,生成新虛擬 DOM,啟動更新流程。

2. Render 階段(異步可中斷,構建 Fiber 樹)

  • 任務拆分與優先級調度:利用?時間切片?將渲染任務拆分為微任務,通過調度器按優先級異步執行,可被高優先級任務中斷。
  • Fiber 樹構建與 Diff 執行
    • 深度優先遍歷,通過?beginWork?對比新舊虛擬 DOM,復用?key?和類型相同的節點,標記新增 / 更新 / 刪除的?副作用(effectTag)
    • 子節點 Diff 按 “單節點匹配 → 末尾增刪 → 復雜移動” 順序優化,減少 DOM 操作。
  • 副作用收集:通過?completeUnitOfWork?自底向上合并副作用,形成根節點的?effectList 鏈表
  • 中斷與恢復:每處理完一個 Fiber 節點,檢查時間片是否耗盡,耗盡時暫停任務并保存進度,瀏覽器空閑時恢復。

3. Commit 階段(同步不可中斷,更新真實 DOM)

  • 遍歷?effectList,批量執行 DOM 操作(創建、刪除、更新節點),確保操作原子性。
  • 觸發生命周期回調(如?useEffectref?更新),完成視圖渲染。

4. 雙緩存機制切換

  • 構建完成的?WorkInProgress Tree?替換為?Current Tree,通過?alternate?指針復用節點數據,保證視圖連續性。

5. 調度系統核心支撐

  • 通過?四層架構(SchedulerHostConfig、Scheduler、SchedulerWithReactIntegration、ReactFiberScheduler)實現任務優先級管理、時間切片和異步調度,避免主線程阻塞。

七、組件觸發渲染的時機

  • 狀態(state)更新:調用更新函數導致組件狀態變化。
  • props 變化:父組件傳遞的 props 值或引用發生改變。
  • 上下文(Context)變化:組件依賴的 Context 值更新。
  • 父組件渲染:父組件重新渲染觸發子組件默認更新(未優化時)。
  • 強制更新:調用forceUpdate()跳過常規更新判斷。
  • 組件 key 變化:觸發舊組件卸載和新組件掛載(相當于重新渲染)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87981.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87981.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87981.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【破局痛點,賦能未來】領碼 SPARK:鑄就企業業務永續進化的智慧引擎—— 深度剖析持續演進之道,引領數字化新范式

摘要 在瞬息萬變的數字時代,企業對業務連續性、敏捷創新及高效運營的需求日益迫切。領碼 SPARK 融合平臺,秉持“持續演進”這一核心理念,以 iPaaS 與 aPaaS 為雙擎驅動,深度融合元數據驅動、智能端口調度、自動化灰度切換、AI 智…

掌握C++核心特性

目標: 掌握C核心特性,為嵌入式開發打基礎 好的,我來為你詳細梳理一下 繼承與多態、虛函數 相關的知識點,包括單繼承、多繼承、虛函數表機制、純虛函數與抽象類、動態綁定。以下內容適合中等難度層次的理解,便于考試復…

python的高校教師資源管理系統

目錄 技術棧介紹具體實現截圖系統設計研究方法:設計步驟設計流程核心代碼部分展示研究方法詳細視頻演示試驗方案論文大綱源碼獲取/詳細視頻演示 技術棧介紹 Django-SpringBoot-php-Node.js-flask 本課題的研究方法和研究步驟基本合理,難度適中&#xf…

Java Collections工具類:高效集合操作

Collections工具類概述 Collections是Java提供的集合操作工具類&#xff0c;位于java.util包中&#xff0c;包含大量靜態方法&#xff0c;用于對List、Set、Map等集合進行排序、查找、替換、同步化等操作。 常用方法及代碼示例 排序操作 sort(List<T> list)&#xff1a…

vue指令總結

vue指令總結 一、總述 二、代碼實現&#xff08;內含大量注釋&#xff09; <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>vue入門</title><!-- 使用Vue 3官方CDN --><script src"https://unpkg.c…

RUP——統一軟件開發過程

RUP概述 RUP&#xff08;Rational Unified Process&#xff09;&#xff0c;統一軟件開發過程&#xff0c;統一軟件過程是一個面向對象且基于網絡的程序開發方法論。 在RUP中采用“41”視圖模型來描述軟件系統的體系結構。“41”視圖包括邏輯視圖、實現視圖、進程視圖、部署視…

SpringBoot電腦商城項目--增加減少購物車商品數量

1. 持久層 1.1 規劃sql語句 執行更新t_cart表記錄的num值根據cid查詢購物車的數據是否存在 select * from t_cart where cid#{cid} 1.2 接口和抽象方法 /*** 獲取購物車中商品的數據總數* return 購物車中商品的數據總數*/Cart findByCid(Integer cid); 1.3 xml文件中sql映射…

零基礎學習Redis(13) -- Java使用Redis命令

上期我們學習了如何使用Java連接到redis&#xff0c;這期我們來學習如何在java中使用redis中的一些命令 1. set/get 可以看到jedis類中提供了很多set方法 public static void test1(Jedis jedis) {jedis.flushAll();jedis.set("key1", "v1");jedis.set(&q…

解決OSS存儲桶未創建導致的XML錯誤

前言 在Java開發中&#xff0c;集成對象存儲服務&#xff08;OSS&#xff09;時&#xff0c;開發者常會遇到一個令人困惑的錯誤提示&#xff1a; “This XML file does not appear to have any style information associated with it. The document tree is shown below.” 此…

Spring 表達式語言(SpEL)深度解析:從基礎到高級實戰指南

目錄 一、SpEL是什么&#xff1f;為什么需要它&#xff1f; 核心價值&#xff1a; 典型應用場景&#xff1a; 二、基礎語法快速入門 1. 表達式解析基礎 2. 字面量表示 3. 屬性訪問 三、SpEL核心特性詳解 1. 集合操作 2. 方法調用 3. 運算符大全 4. 類型操作 四、Sp…

算法導論第二十四章 深度學習前沿:從序列建模到創造式AI

第二十四章 深度學習前沿&#xff1a;從序列建模到創造式AI 算法的進化正在重新定義人工智能的邊界 深度學習作為機器學習領域最活躍的分支&#xff0c;正以驚人的速度推動著人工智能的發展。本章將深入探討五大前沿方向&#xff0c;通過原理分析、代碼實現和應用場景展示&…

抽象工廠設計模式

1.問題背景&#xff1a; 現在有兩個產品(Product)分別是手機殼(PhoneCase)和耳機(EarPhone)&#xff0c;但是他們會來自于各個生產廠商&#xff0c;比如說Apple和Android等等 那么至少會有四個產品&#xff0c;分別是安卓手機殼&#xff0c;安卓耳機&#xff0c;蘋果手機殼&a…

GESP 3級 C++ 知識點總結

根據GESP考試大綱 (2024年3月版)&#xff0c;幫大家總結一下GESP 3級 C語言的知識點&#xff1a; 核心目標&#xff1a; 掌握C程序的基本結構&#xff0c;理解并能運用基礎的編程概念解決稍復雜的問題&#xff0c;重點是函數、一維數組和字符串處理。 主要知識點模塊&#x…

騰訊云主動型云蜜罐技術解析:云原生威脅狩獵的革新實踐(基于騰訊云開發者社區技術網頁與行業實踐)

摘要 騰訊云主動型云蜜罐&#xff08;Active Cloud Honeypot&#xff09;通過動態誘捕機制和云原生架構&#xff0c;在威脅檢測效率、攻擊鏈還原深度、防御聯動實時性等維度實現突破。相較于傳統蜜罐&#xff0c;其核心優勢體現在&#xff1a; 部署效率&#xff1a;分鐘級完成…

企業微信wecom/jssdk的使用(入門)

概述 記錄一個企業微信jssdk的使用&#xff0c;因為要用到圖片上傳、掃描二維碼等工具。項目是uniapp開發的h5項目&#xff0c;fastadmin&#xff08;thinkphp5&#xff09;后端 先看官方文檔 https://developer.work.weixin.qq.com/document/path/90547#%E5%BA%94%E7%94%A8…

大零售生態下開源鏈動2+1模式、AI智能名片與S2B2C商城小程序的協同創新研究

摘要&#xff1a;在流量紅利消退、零售形態多元化的背景下&#xff0c;大零售生態成為商業發展的新趨勢。本文聚焦開源鏈動21模式、AI智能名片與S2B2C商城小程序在零售領域的協同應用&#xff0c;探討其如何打破傳統零售邊界&#xff0c;實現流量變現與用戶資產化。研究表明&am…

Scrapy全流程(一)

創建一個scrapy項目:scrapy startproject mySpider 生成一個爬蟲:scrapy genspider douban movie.douban.com 提取數據:完善spider&#xff0c;使用xpath等方法 保存數據:pipeline中保存數據 2 創建scrapy項目 下面以抓取豆瓣top250來學習scrapy的入門使用&#xff1a;豆瓣…

【Elasticsearch】TF-IDF 和 BM25相似性算法

在 Elasticsearch 中&#xff0c;TF-IDF 和 BM25 是兩種常用的文本相似性評分算法&#xff0c;但它們的實現和應用場景有所不同。以下是對這兩種算法的對比以及在 Elasticsearch 中的使用情況&#xff1a; TF-IDF - 定義與原理&#xff1a;TF-IDF 是一種經典的信息檢索算法&am…

【QT】控件二(輸入類控件、多元素控件、容器類控件與布局管理器)

文章目錄 1.輸入類控件1.1 LineEdit1.2 Text Edit1.3 Combo Box1.4 SpinBox1.5 Date Edit & Time Edit1.6 Dial1.7 Slider 2. 多元素控件2.1 List Widget2.2 Table Widget2.3 Tree Widget 3. 容器類控件3.1 Group Box3.2 Tab Widget 4. 布局管理器4.1 垂直布局4.2 水平布局…

【Docker基礎】Docker鏡像管理:docker pull詳解

目錄 1 Docker鏡像基礎概念 1.1 什么是Docker鏡像&#xff1f; 1.2 鏡像與容器的關系 1.3 鏡像倉庫(Registry) 2 docker pull命令詳解 2.1 基本語法 2.2 參數解釋 2.3 拉取鏡像的基本流程 2.4 鏡像分層結構解析 3 docker pull實戰指南 3.1 基本使用示例 3.2 指定鏡…