文章中英模式
布魯斯前端React面試題目 - Virtual DOM 與 React Fiber 解析
深入理解React的Virtual DOM機制與Fiber架構,包括工作原理、效能優化、key的作用以及常見面試題解析。
文章中英模式

懶得看文章?那就來看影片吧
Virtual DOM:原理與優勢
什麼是 Virtual DOM?
Virtual DOM (虛擬 DOM) 是 React 中的一個核心概念,它是真實 DOM 的一種輕量級、純 JavaScript 的表示形式。本質上,它是一個用來描述 DOM 結構及其屬性的 JavaScript 對象樹。
當應用狀態變化時,React 不會直接操作真實 DOM,而是先在記憶體中更新這個虛擬表示,然後通過一個稱為「協調」(Reconciliation) 的過程,高效地計算出需要對實際 DOM 進行的最小更新。
Virtual DOM 表示
// 一個 Virtual DOM 節點的簡化示例
const virtualDOMNode = {
type: 'div',
props: {
className: 'container',
children: [
{
type: 'h1',
props: {
children: '標題'
}
},
{
type: 'p',
props: {
children: '段落內容'
}
}
]
}
};
// 實際上 React 中的 Virtual DOM 結構更加複雜對應的 HTML
<!-- 上面 Virtual DOM 對應的實際 HTML -->
<div class="container">
<h1>標題</h1>
<p>段落內容</p>
</div>為什麼需要 Virtual DOM?
操作真實 DOM 是昂貴的,每次直接修改 DOM 會導致瀏覽器進行重排 (reflow) 和重繪 (repaint),特別是在需要頻繁更新 UI 的現代應用中,這會帶來性能瓶頸。
DOM 操作的性能問題
- 1. 重排和重繪消耗大量計算資源
- 2. 頻繁的 DOM 操作會導致頁面性能下降
- 3. 直接修改 DOM 難以追蹤變化
- 4. 直接操作 DOM 的代碼難以維護和調試
Virtual DOM 的優勢
- 1. 將多次 DOM 操作合併為一次更新
- 2. 高效計算出最小必要的 DOM 變更
- 3. 降低了重排和重繪的次數
- 4. 提供了聲明式的 UI 編程模型
- 5. 使跨平台開發變得更加容易
Virtual DOM 的工作流程
React 從 JSX 到頁面渲染的完整流程如下:
通俗解釋:
- 1. Virtual DOM:就像草稿紙,先在上面畫草圖,而不直接在牆上畫
- 2. Fiber:把大工作分成小塊,可以隨時暫停處理更重要的事
- 3. Diffing:比較新舊草圖,只標記需要改動的部分
- 4. Reconciliation:規劃階段,決定哪些需要更新
- 5. Commit:執行階段,把變更真正應用到 DOM
- 6. useLayoutEffect:在畫面顯示前執行,可以測量和調整 DOM
- 7. useEffect:在畫面顯示後執行,適合處理不急的任務
Virtual DOM Diffing 算法
Diffing 算法是 Virtual DOM 高效性的關鍵。React 實現了一個 O(n) 算法,基於兩個假設:
1. 不同類型元素產生不同樹
如果元素從 div 變成 span,React 會完全重建樹,而不是嘗試匹配。
2. 使用 key 標識穩定元素
添加 key 幫助 React 識別哪些元素是新增、移動或刪除的。
為什麼需要 key?
// 沒有 key 時,React 難以識別變化
<ul>
<li>首頁</li>
<li>關於我們</li>
</ul>
// 有 key 時,React 能精確識別
<ul>
<li key="home">首頁</li>
<li key="about">關於我們</li>
</ul>性能提示:Virtual DOM 通常比直接操作 DOM 更高效,但並非在所有場景都是最快的。React 的優勢在於提供良好的開發體驗和合理的性能平衡。
React Fiber:現代協調引擎
什麼是 React Fiber?
React Fiber 是 React 16 引入的協調引擎,重寫了 React 核心算法。它的主要目標是讓 React 能更好地處理大型應用,特別是通過可中斷渲染提高應用響應性。
核心改進:Fiber 之前,React 渲染過程一旦開始就無法中斷,可能阻塞主線程導致頁面卡頓。Fiber 讓渲染過程可以被打斷,優先處理用戶交互。
Fiber 架構的關鍵特性
工作可中斷與恢復
就像在寫一份長報告時,可以先暫停去接電話,然後再回來繼續寫。React Fiber 也是如此,當用戶需要點擊按鈕時,可以暫停正在進行的渲染工作,優先響應用戶操作。
優先級排序
類似醫院的急診分類,危急病人優先處理。React 也會優先處理用戶交互(如按鈕點擊動畫)而非後台數據更新,確保良好的用戶體驗。
Virtual DOM 與 React Fiber 的關係
Virtual DOM 和 React Fiber 雖然是不同概念,但在 React 中緊密協作:
| 方面 | Virtual DOM | React Fiber |
|---|---|---|
| 是什麼 | DOM的JS對象表示 | 協調引擎 |
| 作用 | 描述UI應該是什麼樣子 | 決定如何和何時更新UI |
| 更新方式 | 一次性完成 | 可分段、可中斷 |
簡單理解:
- 1. Virtual DOM 告訴 React 「要做什麼」(UI 應該長什麼樣)
- 2. Fiber 決定 「如何做」(如何高效地更新 DOM)
兩者結合讓 React 既能提供良好的開發體驗(聲明式編程),又能保持出色的性能和響應性。
🔥 常見面試題目
(一)什麼是 Virtual DOM,它如何提升 React 的效能?
解答:
Virtual DOM 是真實 DOM 的 JavaScript 對象表示。就像是一個藍圖,描述了頁面結構但不是真正的頁面。
提升效能的方式:
- 1. 批量更新:先在記憶體中計算所有變化,再一次性更新真實 DOM
- 2. 減少操作:只更新真正需要變化的部分,不重繪整個頁面
- 3. 跨平台:同一套邏輯可以渲染到網頁、手機應用等不同平台
簡單例子:
// Virtual DOM 表示
const vdom = {
type: 'div',
props: { className: 'container' },
children: [
{ type: 'h1', props: { children: '標題' } },
{ type: 'p', props: { children: '內容' } }
]
}需要注意的是,Virtual DOM 不一定總是比直接操作 DOM 更快,但它讓開發者可以用更簡單的方式構建複雜的 UI,同時保持合理的性能。
(二)React Fiber 架構的目的是什麼?它如何改進了 React 的渲染機制?
解答:
Fiber 架構的目的是讓 React 應用更流暢,特別是在處理大量數據和複雜界面時。它就像是把一個大工作分成小塊,可以隨時暫停去處理更重要的事情。
主要改進:
- 1. 可中斷渲染:長任務可以分段執行,不阻塞主線程
- 2. 優先級排序:用戶交互可以優先於後台更新
- 3. 錯誤處理:一個組件出錯不會導致整個應用崩潰
舊版 React
Fiber 架構
Fiber 將渲染分為兩個階段:「準備階段」(可中斷)決定要做什麼變更,「提交階段」(不可中斷)將變更應用到 DOM。這讓 React 能夠在保持頁面響應的同時處理複雜更新。
(三)解釋 React 中 key 屬性的重要性,以及如何正確使用它?
解答:
key 屬性就像是列表中每個項目的「身份證」,幫助 React 識別哪些項目變化了、新增了或刪除了。
為什麼重要:
- 1. 幫助 React 高效更新列表,不需要重建所有項目
- 2. 保持組件狀態,避免在位置變化時丟失
- 3. 減少不必要的重渲染,提高性能
正確使用方式:
// ❌ 不好:使用索引作為key
<ul>
<li>首頁</li>
<li>關於我們</li>
</ul>
// ✅ 好:使用唯一ID
<ul>
<li key="home">首頁</li>
<li key="about">關於我們</li>
</ul>使用 key 的規則:
- 1. 在同級元素中必須唯一
- 2. 應該保持穩定,不要隨機生成
- 3. 盡量使用數據的ID,避免使用索引
使用索引作為 key 在項目順序變化時會導致問題,因為索引會變但內容可能不變,React 會誤解情況。最好使用來自數據的穩定ID作為 key。
(四)解釋 Virtual DOM 的工作流程,每個階段在做什麼?
解答:
Virtual DOM 的工作流程可以分為幾個關鍵階段,每個階段都有特定的任務:
1. 建立 Virtual DOM 樹
React 將 JSX 轉換為 JavaScript 對象,形成虛擬 DOM 樹。
// JSX
<div className="container">
<h1>標題</h1>
</div>
// 轉換為 Virtual DOM 對象
{
type: 'div',
props: {
className: 'container',
children: [{
type: 'h1',
props: { children: '標題' }
}]
}
}2. Diffing 比較階段
當狀態更新時,React 創建新的虛擬 DOM 樹,並與舊樹進行比較,找出差異。
舊樹
div (container) ├─ h1: "舊標題" └─ p: "舊內容"
新樹
div (container) ├─ h1: "新標題" └─ p: "舊內容"
↓ Diff 結果:只需更新 h1 的文本內容
3. Reconciliation 協調階段
根據 Diff 結果,React 計算出需要對 DOM 進行的最小更改。這個階段是可中斷的,允許瀏覽器處理更高優先級的任務。
// 偽代碼:協調階段的工作單元
{
type: 'UPDATE',
element: h1Element,
newProps: { children: '新標題' },
priority: 'normal'
}4. Commit 提交階段
將計算好的變更應用到實際 DOM。這個階段是不可中斷的,一旦開始就會完成所有更新。
// 偽代碼:DOM 更新操作
h1Element.textContent = '新標題';5. 生命週期與 Hooks 執行
DOM 更新後:執行 useLayoutEffect
瀏覽器繪製後:執行 useEffect
通俗來說,整個流程就像裝修房子:
- 1. 先在紙上畫設計圖(Virtual DOM)
- 2. 比較新舊設計圖,標記需要改動的地方(Diffing)
- 3. 規劃施工順序,可以分階段進行(Reconciliation)
- 4. 實際動工改造房子(Commit)
- 5. 檢查施工結果並做最後調整(生命週期與 Hooks)
這種方式讓 React 能夠高效地更新 UI,同時保持良好的用戶體驗,特別是在複雜應用中。