Back to Blog
By AriesZhou · · 4 min read

Virtual DOM

React

When you update state in React, how does the page update efficiently? Why is directly manipulating the real DOM slow, and how does the virtual DOM solve this? This article takes a deep dive into React’s most fundamental mechanism.

The virtual DOM is a core concept in React and other modern frontend frameworks. Understanding how it works is essential for writing more efficient code.

1. What is the virtual DOM

The virtual DOM is a JavaScript object that represents the structure of the real DOM:

// 这样的 JSX
<div className="container">
  <h1>标题</h1>
  <p>内容</p>
</div>

// 会被编译成这样的 JavaScript 对象(虚拟 DOM)
{
  type: 'div',
  props: { className: 'container' },
  children: [
    { type: 'h1', props: {}, children: ['标题'] },
    { type: 'p', props: {}, children: ['内容'] }
  ]
}

2. How it works

2.1 Overall flow

graph TD
    A[State 变化] --> B[生成新虚拟 DOM]
    B --> C[Diff 算法比较]
    C --> D[计算最小变更]
    D --> E[批量更新真实 DOM]

2.2 Steps

function Counter() {
  const [count, setCount] = useState(0);

  // 点击按钮触发:
  // 1. setCount(1) 更新 state
  // 2. React 重新渲染组件
  // 3. 生成新的虚拟 DOM
  // 4. 与旧虚拟 DOM 比较(Diff)
  // 5. 计算最小变更
  // 6. 更新真实 DOM

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>增加</button>
    </div>
  );
}

3. The diff algorithm

3.1 Core principles

React’s diff algorithm is based on two assumptions:

  1. Different element types produce different trees: when an element’s type changes, React tears down the entire old tree and builds a new one
  2. Developers can hint which child elements are stable using keys

3.2 Comparison example

// 旧
<ul>
  <li key="a">A</li>
  <li key="b">B</li>
</ul>

// 新 - 仅仅移动了位置
<ul>
  <li key="b">B</li>
  <li key="a">A</li>
</ul>

// React 只会交换位置,不会重新创建 DOM 节点

3.3 The importance of keys

// ❌ 避免:使用数组索引作为 key
{items.map((item, index) => (
  <TodoItem key={index} item={item} />
))}

// ✅ 推荐:使用唯一 ID
{items.map(item => (
  <TodoItem key={item.id} item={item} />
))}

Note: keys should be stable, unique, and immutable.


4. Performance optimization

4.1 Avoiding unnecessary renders

// ❌ 每次渲染都创建新对象
function Component() {
  return <div style={{ color: 'red' }}>内容</div>;
}

// ✅ 使用 useMemo 或外部定义
const styles = { color: 'red' };
function Component() {
  return <div style={styles}>内容</div>;
}

4.2 Using keys properly

// ❌ key 使用随机值会导致性能问题
items.map(item => (
  <Item key={Math.random()} />
))

// ✅ 稳定的 key 帮助 Diff 算法
items.map(item => (
  <Item key={item.id} />
))

4.3 Component splitting

// ❌ 大组件:任何变化都导致整个组件重渲染
function Dashboard() {
  const [user, setUser] = useState(null);
  const [posts, setPosts] = useState([]);
  const [comments, setComments] = useState([]);
  const [notifications, setNotifications] = useState([]);

  // 用户点击任意按钮,整个 Dashboard 都会重新渲染
  return (
    <div>
      <UserProfile user={user} />
      <PostList posts={posts} />
      <CommentSection comments={comments} />
      <NotificationPanel notifications={notifications} />
    </div>
  );
}

// ✅ 拆分后:变化隔离
// 每个子组件独立,使用 React.memo 避免不必要渲染
const UserProfile = memo(({ user }) => <div>{user.name}</div>);
const PostList = memo(({ posts }) => <ul>{posts.map(p => <li>{p.title}</li>)}</ul>);
const CommentSection = memo(({ comments }) => <div>{comments.length} 条评论</div>);
const NotificationPanel = memo(({ notifications }) => <div>{notifications.length} 条通知</div>);

function Dashboard() {
  const [user, setUser] = useState(null);
  const [posts, setPosts] = useState([]);
  const [comments, setComments] = useState([]);
  const [notifications, setNotifications] = useState([]);

  // 只有 user 变化时,UserProfile 才会重新渲染
  // posts, comments, notifications 的变化不会相互影响
  return (
    <div>
      <UserProfile user={user} />
      <PostList posts={posts} />
      <CommentSection comments={comments} />
      <NotificationPanel notifications={notifications} />
    </div>
  );
}

5. Summary of pros and cons

5.1 Pros

ProsDescription
Performance optimizationReduces the number of real DOM operations
Cross-platformThe same code can run on multiple platforms
Developer experienceDeclarative API simplifies code logic

5.2 Drawbacks

DrawbackSolution
Initial render overheadCode splitting, lazy loading
Memory usageSplit components appropriately
Not always optimalManipulate the DOM directly when necessary

6. Real DOM vs Virtual DOM

// 直接操作真实 DOM(慢)
const element = document.getElementById('root');
element.innerHTML = '<div>内容</div>';
element.style.color = 'red';

// 虚拟 DOM(快)
// React 会在内存中比较差异,批量更新
setContent('内容');
setColor('red');
// 最终只执行一次 DOM 操作

7. Summary

The virtual DOM is central to React’s performance:

  • Declarative: Describes “what” rather than “how”
  • Efficient: The diff algorithm minimizes DOM operations
  • Cross-platform: React Native, React 3D, etc.

Understanding how the virtual DOM works helps you design and optimize React applications more effectively.