Frontend Development 7 min read

Understanding Virtual DOM: Concepts, Implementation, and Mapping to Real DOM

The article explains the Virtual DOM as a lightweight JavaScript object with tag, props, and children, shows how JSX compiles to VD using a custom pragma, provides helper functions to create real DOM from VD, and outlines how batching updates reduces reflows, previewing a future diff algorithm.

Youzan Coder
Youzan Coder
Youzan Coder
Understanding Virtual DOM: Concepts, Implementation, and Mapping to Real DOM

The article introduces the concept of Virtual DOM (VD) as a lightweight JavaScript object that abstracts a real DOM node. A VD object minimally contains three properties: tag , props , and children . Different frameworks may name these properties differently, but they all represent the element name, its attributes, and its child nodes.

A typical VD example is shown:

{
  tag: "div",
  props: {},
  children: [
    "Hello World",
    {
      tag: "ul",
      props: {},
      children: [{
        tag: "li",
        props: { id: 1, class: "li-1" },
        children: ["第", 1]
      }]
    }
  ]
}

This VD corresponds to the following HTML:

<div>
  Hello World
  <ul>
    <li id="1" class="li-1">第1</li>
  </ul>
</div>

Using VD can reduce the number of DOM re‑flows and repaint operations, thereby improving rendering efficiency. The article breaks the page update process into three stages: JavaScript calculation, render‑tree generation, and painting. By batching operations at the VD level, the number of expensive render‑tree generations and paints can be lowered.

Implementation details are provided step‑by‑step:

Compile JSX to a function that returns VD objects. Example JSX compilation:

function render() {
  return (
Hello World
第1
);
}

After JSX compilation (with a custom pragma "h"), the code becomes:

function render() {
  return h('div', null,
    'Hello World',
    h('ul', null,
      h('li', { id: '1', class: 'li-1' }, '\u7B2C1')
    )
  );
}

The Babel configuration to set the pragma:

{
  "plugins": [
    ["transform-react-jsx", { "pragma": "h" }]
  ]
}

The helper functions used are:

function flatten(arr) {
  return [].concat.apply([], arr);
}

function h(tag, props, ...children) {
  return {
    tag,
    props: props || {},
    children: flatten(children) || []
  };
}

To convert a VD tree back to real DOM, the following functions are defined:

function createElement(vdom) {
  if (typeof vdom === 'string' || typeof vdom === 'number') {
    return document.createTextNode(vdom);
  }
  const { tag, props, children } = vdom;
  const element = document.createElement(tag);
  setProps(element, props);
  children.map(createElement).forEach(element.appendChild.bind(element));
  return element;
}

function setProps(element, props) {
  for (let key in props) {
    element.setAttribute(key, props[key]);
  }
}

Running createElement on the VD object produces the real DOM structure, which can then be inserted into the page.

The article concludes by stating that the next installment will implement a simple VD diff algorithm to detect changes between two VD trees and update the real DOM efficiently.

Front-endJavaScriptweb developmentJSXvirtual-domdiff algorithm
Youzan Coder
Written by

Youzan Coder

Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.