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.
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.
Youzan Coder
Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.