深入理解React 渲染機制
引言
React 作為當今最流行的前端框架之一,其高效的渲染機制是核心優(yōu)勢。理解 React 如何渲染 UI,對于性能優(yōu)化至關(guān)重要。本文將深入探討虛擬 DOM、Diff 算法、Fiber 架構(gòu)以及完整的渲染流程。
虛擬 DOM 原理與優(yōu)勢
虛擬 DOM(Virtual DOM)是 React 的核心概念,它是一個輕量級的 JavaScript 對象,用來描述真實 DOM 的結(jié)構(gòu)。
工作原理:
- 首次渲染時,React 創(chuàng)建虛擬 DOM 樹并映射到真實 DOM
- 狀態(tài)變化時,生成新的虛擬 DOM 樹
- 通過 Diff 算法比較兩棵樹的差異
- 將最小變更應用到真實 DOM
核心優(yōu)勢:
- 減少直接操作真實 DOM 的次數(shù)
- 批量更新,提升性能
- 跨平臺能力(React Native 等)
// 虛擬 DOM 示例
const element = {
type: 'div',
props: {
className: 'container',
children: {
type: 'h1',
props: { children: 'Hello React' }
}
}
};
Diff 算法三大策略
React 的 Diff 算法通過三大策略將 O(n³) 復雜度優(yōu)化到 O(n):
1. 同層比較
React 只比較同一層級的節(jié)點,不會跨層級比較。如果節(jié)點類型不同,直接銷毀舊節(jié)點并創(chuàng)建新節(jié)點。
// 同層比較示例 // 舊樹 // 新樹 <div> <div> <Component /> <Component /> </div> </div> // ? 只比較 div 的子節(jié)點
2. 類型判斷
節(jié)點類型相同時,復用節(jié)點;類型不同時,銷毀重建。
// 類型相同 - 復用 <div className="old"> → <div className="new"> // 類型不同 - 重建 <div> → <span> // 銷毀 div,創(chuàng)建 span
3. Key 的作用
Key 幫助 React 識別哪些元素發(fā)生了變化,特別在列表渲染中至關(guān)重要。
// ? 不推薦 - 使用索引作為 key
{items.map((item, index) => (
<li key={index}>{item.name}</li>
))}
// ? 推薦 - 使用唯一 ID
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
Fiber 架構(gòu)詳解
React 16 引入的 Fiber 架構(gòu)解決了大規(guī)模組件樹渲染阻塞的問題。
節(jié)點結(jié)構(gòu)
每個 Fiber 節(jié)點包含:
type: 組件類型props: 屬性return: 父節(jié)點child: 子節(jié)點sibling: 兄弟節(jié)點effectTag: 副作用標記
雙緩沖機制
Fiber 使用雙緩沖(Double Buffering)技術(shù):
- current 樹: 當前屏幕上顯示的 Fiber 樹
- workInProgress 樹: 正在構(gòu)建的新 Fiber 樹
渲染完成后,直接替換指針,實現(xiàn)快速切換。
任務優(yōu)先級
Fiber 將渲染任務拆分為可中斷的小單元,根據(jù)優(yōu)先級調(diào)度:
| 優(yōu)先級 | 場景 |
|---|---|
| Immediate | 用戶輸入、文本選擇 |
| UserBlocking | 點擊、滾動 |
| Normal | 網(wǎng)絡請求、數(shù)據(jù)加載 |
| Low | 分析上報 |
| Idle | 后臺任務 |
完整渲染流程
React 渲染分為兩個階段:
Render 階段(可中斷)
- 從根 Fiber 開始遍歷
- 調(diào)用組件的 render 方法
- 比較新舊虛擬 DOM,標記變更
- 可被高優(yōu)先級任務中斷
// Render 階段示例
function App() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
// 點擊時觸發(fā) Render 階段
Commit 階段(不可中斷)
- 應用所有變更到真實 DOM
- 調(diào)用生命周期鉤子(componentDidMount 等)
- 觸發(fā) useEffect 回調(diào)
- 必須同步完成,不可中斷
Render 階段 → 標記變更 → Commit 階段 → 更新 DOM
(可中斷) (不可中斷)
性能優(yōu)化實踐
1. 使用 React.memo
const MemoComponent = React.memo(({ data }) => {
return <div>{data}</div>;
});
// 僅在 props 變化時重新渲染
2. 使用 useMemo 緩存計算結(jié)果
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b);
}, [a, b]);
// 依賴不變時復用緩存值
3. 使用 useCallback 緩存函數(shù)
const handleClick = useCallback(() => {
doSomething(a, b);
}, [a, b]);
// 避免子組件因函數(shù)引用變化而重渲染
4. 列表渲染優(yōu)化
// 虛擬列表 - 只渲染可見區(qū)域
import { FixedSizeList } from 'react-window';
<FixedSizeList
height={500}
itemCount={1000}
itemSize={35}
>
{({ index, style }) => (
<div style={style}>Item {index}</div>
)}
</FixedSizeList>
5. 代碼分割
// 懶加載組件
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<LazyComponent />
</Suspense>
);
}
總結(jié)
React 渲染機制的核心要點:
- 虛擬 DOM 減少真實 DOM 操作,提升性能
- Diff 算法 通過同層比較、類型判斷、Key 識別實現(xiàn) O(n) 復雜度
- Fiber 架構(gòu) 支持可中斷渲染和任務優(yōu)先級調(diào)度
- 雙階段渲染 Render 可中斷,Commit 不可中斷
- 性能優(yōu)化 合理使用 memo、useMemo、useCallback 等工具
理解這些機制,能幫助我們在開發(fā)中做出更優(yōu)的性能決策,構(gòu)建流暢的用戶體驗。
到此這篇關(guān)于深入理解React 渲染機制的文章就介紹到這了,更多相關(guān)React 渲染機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Ant Design與Ant Design pro入門使用教程
Ant Design 是一個服務于企業(yè)級產(chǎn)品的設(shè)計體系,組件庫是它的 React 實現(xiàn),antd 被發(fā)布為一個 npm 包方便開發(fā)者安裝并使用,這篇文章主要介紹了Ant Design與Ant Design pro入門,需要的朋友可以參考下2023-12-12
解決react中useState狀態(tài)異步更新的問題
本文主要介紹了react中useState狀態(tài)異步更新的問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07
React+TS+IntersectionObserver實現(xiàn)視頻懶加載和自動播放功能
通過本文的介紹,我們學習了如何使用 React + TypeScript 和 IntersectionObserver API 來實現(xiàn)一個視頻播放控制組件,該組件具有懶加載功能,只有在用戶滾動頁面且視頻進入視口時才開始下載視頻資源,需要的朋友可以參考下2023-04-04

