深入理解React Fiber機(jī)制
React Fiber 是 React 16 引入的核心協(xié)調(diào)算法重構(gòu),它解決了舊版 Stack Reconciler 的不可中斷、同步遞歸導(dǎo)致的卡頓問題。
簡(jiǎn)單來說:Fiber 讓 React 的渲染過程從「一口氣干完」變成了「可中斷、可分片、可優(yōu)先級(jí)排序」的任務(wù)調(diào)度。
下面從三個(gè)關(guān)鍵維度展開:
一、為什么需要 Fiber?(痛點(diǎn)分析)
舊版 React(<16)的 Stack Reconciler 有致命缺陷:
- 同步遞歸:遍歷整個(gè)虛擬 DOM 樹時(shí),一旦開始就無法停止。
- 阻塞主線程:如果組件層級(jí)很深(幾百個(gè)),一次更新可能占用 100ms+ 的 JS 執(zhí)行時(shí)間。
- 導(dǎo)致掉幀:瀏覽器需要 16.6ms 渲染一幀(60fps),而 React 長(zhǎng)期霸占主線程,用戶點(diǎn)擊、動(dòng)畫都會(huì)卡頓。
典型案例:一個(gè)輸入框綁定大列表更新,每次按鍵都重新渲染整個(gè)列表,造成明顯延遲。
Fiber 的目標(biāo)就是:把同步不可中斷的工作,拆解成異步可中斷的小任務(wù)單元。
二、Fiber 的核心機(jī)制
1. Fiber 是什么?(數(shù)據(jù)結(jié)構(gòu) + 工作單元)
Fiber 既是數(shù)據(jù)結(jié)構(gòu),也是執(zhí)行單元:
作為數(shù)據(jù)結(jié)構(gòu):每個(gè) React 元素對(duì)應(yīng)一個(gè) Fiber 節(jié)點(diǎn),構(gòu)成 Fiber 樹(鏈表結(jié)構(gòu),而非樹)。
// Fiber 節(jié)點(diǎn)的核心字段
{
tag: 5, // 節(jié)點(diǎn)類型(函數(shù)組件、類組件、DOM等)
key: null,
type: 'div',
return: parentFiber, // 指向父 Fiber(完成后的返回目標(biāo))
child: childFiber, // 指向第一個(gè)子 Fiber
sibling: siblingFiber,// 指向下一個(gè)兄弟 Fiber
pendingProps: {}, // 新傳入的 props
memoizedProps: {}, // 上次渲染的 props
memoizedState: null, // 上次渲染的 state(用于 Hooks)
alternate: null, // 雙緩存中的另一個(gè) Fiber(current <-> workInProgress)
}
作為執(zhí)行單元:Fiber 節(jié)點(diǎn)記錄了自身的「進(jìn)度信息」,React 可以在中斷后從任意 Fiber 繼續(xù)工作。
2. 雙緩存機(jī)制(Double Buffering)
React 維護(hù)兩棵 Fiber 樹:
- current 樹:當(dāng)前屏幕上顯示的內(nèi)容(已提交到 DOM)。
- workInProgress 樹:在內(nèi)存中構(gòu)建的新樹,代表下一次要顯示的界面。
工作流程:
- 觸發(fā)更新時(shí),克隆 current 樹生成 workInProgress 樹。
- 在 workInProgress 樹上進(jìn)行協(xié)調(diào)(diff + 標(biāo)記副作用)。
- 構(gòu)建完成后,
commitRoot將 workInProgress 樹切換為 current 樹(一次指針切換)。 - 復(fù)用
alternate屬性指向另一棵樹,節(jié)省內(nèi)存分配。
好處:可以在構(gòu)建過程中隨時(shí)放棄 workInProgress 樹,不影響用戶當(dāng)前看到的界面。
3. 調(diào)度與優(yōu)先級(jí)(Scheduler)
Fiber 搭配了獨(dú)立的調(diào)度器(Scheduler),實(shí)現(xiàn)了時(shí)間切片和優(yōu)先級(jí)隊(duì)列。
- 任務(wù)拆分:將協(xié)調(diào)過程拆解為多個(gè)「工作單元」(每個(gè) Fiber 節(jié)點(diǎn)的處理就是一個(gè)單元)。
- 時(shí)間切片:每次循環(huán)檢查是否還有剩余時(shí)間(
shouldYield),超時(shí)則中斷并讓出主線程。 - 優(yōu)先級(jí)機(jī)制:
- 離散事件(click、input):立即同步執(zhí)行(最高優(yōu)先級(jí))。
- 連續(xù)事件(scroll、拖拽):下一幀之前執(zhí)行(高優(yōu)先級(jí))。
- 數(shù)據(jù)請(qǐng)求(useEffect、Suspense fallback):可中斷的低優(yōu)先級(jí)。
startTransition標(biāo)記的更新:最低優(yōu)先級(jí),空閑時(shí)執(zhí)行。
簡(jiǎn)單模擬調(diào)度流程:
// 簡(jiǎn)化的 workLoop
function workLoop(deadline) {
let shouldYield = false;
while (nextUnitOfWork && !shouldYield) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork); // 處理一個(gè) Fiber
shouldYield = deadline.timeRemaining() < 1; // 剩余時(shí)間不足 1ms 則中斷
}
if (nextUnitOfWork) {
requestIdleCallback(workLoop); // 有空閑時(shí)間再繼續(xù)
} else {
commitRoot(); // 全部完成,提交 DOM
}
}
requestIdleCallback(workLoop);
三、Fiber 架構(gòu)下的兩個(gè)階段
React 將渲染過程拆解為兩個(gè)截然不同的階段:
| 階段 | 執(zhí)行內(nèi)容 | 是否可中斷 | 是否執(zhí)行副作用 | 常見方法 |
|---|---|---|---|---|
| Render/Reconciliation | 構(gòu)建 Fiber 樹、計(jì)算 diff、標(biāo)記副作用 | ? 可中斷 | ? | render、shouldComponentUpdate、hooks 中的更新計(jì)算 |
| Commit | 將副作用應(yīng)用到真實(shí) DOM、執(zhí)行生命周期 | ? 不可中斷 | ? | componentDidMount、useLayoutEffect、ref 更新 |
重要區(qū)別:
- Render 階段可以被打斷(比如用戶點(diǎn)擊新的高優(yōu)先級(jí)事件),React 會(huì)丟棄當(dāng)前 workInProgress 樹,重新開始。
- Commit 階段必須同步完成,確保 DOM 一致性和用戶看到的結(jié)果。
這也解釋了為什么 componentWillMount 和 componentWillUpdate 被標(biāo)記為不安全 —— 它們可能在 Render 階段被多次調(diào)用或中斷。
四、Fiber 帶來的具體能力
- Concurrent Mode(并發(fā)模式,現(xiàn)為默認(rèn)啟用):渲染和用戶輸入并行處理,不再互相阻塞。
- Suspense:等待異步數(shù)據(jù)(代碼、圖片、數(shù)據(jù))時(shí),渲染 fallback,數(shù)據(jù)就緒后繼續(xù) Fiber 工作。
- useDeferredValue / startTransition:將低優(yōu)先級(jí)更新標(biāo)記為可中斷,保障高優(yōu)先級(jí)響應(yīng)的流暢度。
- 錯(cuò)誤邊界:通過
componentDidCatch捕獲子組件樹的錯(cuò)誤,防止整個(gè)應(yīng)用崩潰。
五、常見面試追問與簡(jiǎn)答
Q:Fiber 架構(gòu)下的 diff 算法有變化嗎?
A:核心策略相同(同級(jí)比較、key 復(fù)用),但實(shí)現(xiàn)上基于 Fiber 鏈表,且 diff 過程是異步可中斷的。
Q:Fiber 有打破 React 聲明式編程的范式嗎?
A:沒有。Fiber 是內(nèi)部實(shí)現(xiàn)優(yōu)化,對(duì)外 API 保持一致,開發(fā)者依然面向狀態(tài)編程。
Q:使用 Fiber 一定能提升性能嗎?
A:不一定。對(duì)于簡(jiǎn)單應(yīng)用,F(xiàn)iber 的調(diào)度開銷可能略微增加總耗時(shí)。主要收益是在復(fù)雜交互場(chǎng)景(輸入框 + 大列表渲染)下保持 UI 流暢。
Q:Fiber 樹和虛擬 DOM 樹是什么關(guān)系?
A:虛擬 DOM 是 React 元素樹(每次 render 重建)。Fiber 樹是持久化的(只更新屬性),通過 alternate 復(fù)用節(jié)點(diǎn),性能更高。
如果你需要進(jìn)一步了解 Fiber 的副作用收集(Effect List) 或Hooks 在 Fiber 上的存儲(chǔ)原理,我可以繼續(xù)展開。
到此這篇關(guān)于深入理解React Fiber機(jī)制的文章就介紹到這了,更多相關(guān)React Fiber 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 深入理解React的Fiber架構(gòu)
- React 中的雙緩存 Fiber 樹機(jī)制詳解
- React Fiber 架構(gòu)解決頁面卡頓問題的全過程
- React Fiber中面試官最關(guān)心的技術(shù)話題
- React-three-fiber使用初體驗(yàn)
- React超詳細(xì)講述Fiber的使用
- React?Fiber構(gòu)建源碼解析
- React?Fiber構(gòu)建completeWork源碼解析
- React?Fiber原理深入分析
- React Fiber與調(diào)和深入分析
- React Fiber源碼深入分析
- React的Fiber的實(shí)現(xiàn), Vue為什么不需要Fiber
相關(guān)文章
創(chuàng)建React項(xiàng)目的三個(gè)方式小結(jié)
本文主要介紹了創(chuàng)建React項(xiàng)目的三個(gè)方式小結(jié),包括create-react-app、Vite和Next.js,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-07-07
react-native 圓弧拖動(dòng)進(jìn)度條實(shí)現(xiàn)的示例代碼
本篇文章主要介紹了react-native 圓弧拖動(dòng)進(jìn)度條實(shí)現(xiàn)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04
react native 文字輪播的實(shí)現(xiàn)示例
這篇文章主要介紹了react native 文字輪播的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07
詳解在create-react-app使用less與antd按需加載
這篇文章主要介紹了詳解在create-react-app使用less與antd按需加載,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12

