Rendering Process and Performance Optimization Principles of Virtual DOM

Rendering Process and Performance Optimization Principles of Virtual DOM

The rendering process of Virtual DOM involves three core stages: creating the virtual DOM tree, diffing (differences comparison), and patching. Below, I will explain each step in detail and discuss the performance optimization strategies within them.

1. Creating the Virtual DOM Tree

  • Description: When a component's state changes, the framework does not directly manipulate the real DOM. Instead, it first constructs a lightweight JavaScript object (virtual node) in memory to describe the real DOM structure.
  • Process:
    • The component's render function executes and returns virtual nodes (vnodes).
    • Each vnode contains information such as tag name, properties, child nodes, etc.
    • The entire component forms a virtual DOM tree.
  • Example:
    // Virtual nodes generated after JSX compilation
    {
      tag: 'div',
      props: { className: 'container' },
      children: [
        {
          tag: 'p',
          props: { onClick: handler },
          children: ['Click Me']
        }
      ]
    }
    

2. Diffing (Diff Algorithm)

  • Core Idea: Compare the old and new virtual DOM trees to find the minimal set of changes.
  • Optimization Strategy 1 - Same-Level Comparison:
    • Only compare nodes at the same hierarchical level; do not move nodes across levels.
    • Time complexity is optimized from O(n³) to O(n).
  • Optimization Strategy 2 - Key Optimization:
    • Add a unique key to list items to help the algorithm identify node identity.
    • Avoid unnecessary re-renders.
  • Node Comparison Rules:
    • Different tag names → Replace the entire node directly.
    • Same tag name → Compare property differences.
    • List nodes → Use a double-pointer algorithm for optimized comparison.

3. Patching

  • Batch Updates: Combine multiple DOM operations into a single batch update.
  • Differentiated Updates:
    • Only update the parts that have actually changed.
    • Avoid reflow and repaint of entire subtrees.
  • Example Process:
    // Pseudo-code example
    function patch(oldVnode, newVnode) {
      if (oldVnode.tag !== newVnode.tag) {
        // Different tags, replace directly
        replaceNode(oldVnode, newVnode)
      } else {
        // Update properties
        updateProps(oldVnode, newVnode)
        // Recursively update child nodes
        updateChildren(oldVnode.children, newVnode.children)
      }
    }
    

4. In-Depth Analysis of Performance Optimization

  • Time Slicing: Break the diff process into multiple small tasks to avoid blocking the main thread.
  • Component-Level Optimization:
    • Use shouldComponentUpdate or memo to avoid unnecessary component renders.
    • Perform virtual DOM comparison only for affected components.
  • Compile-Time Optimization:
    • Vue3's static node hoisting: Extract static content outside the render function.
    • React's compiler optimization: Mark immutable data to reduce comparison depth.

5. Comparison with Traditional Direct DOM Manipulation

  • Advantages:
    • Abstracts DOM operations, making code more predictable.
    • Reduces the number of actual DOM operations through diffing.
    • Provides a foundation for cross-platform rendering (e.g., React Native).
  • Applicable Scenarios:
    • Suitable for large, data-driven applications.
    • May be slightly "heavy" for simple interaction scenarios.

Through this layered optimization strategy, Virtual DOM achieves performance close to manual optimization while ensuring a good development experience.