Creating Your Own Virtual DOM Using JavaScript
Last Updated :
05 May, 2024
The Virtual DOM is a key concept in modern web development, particularly with libraries like React. It allows developers to efficiently update and render changes to the UI without re-rendering the entire DOM. In this article, we’ll walk through creating a simple Virtual DOM implementation using plain JavaScript.
What is Virtual DOM?
Virtual DOM is a lightweight copy of the actual DOM. When there’s a change in the state of an application, the Virtual DOM gets updated first. Then, it calculates the difference between the new Virtual DOM and the old one (a process known as “diffing”). Finally, it updates only the changed parts in the actual DOM, minimizing unnecessary re-renders and improving performance.
Building the Virtual DOM
Let’s start by defining the basic structure for our Virtual DOM nodes.
JavaScript
function createElement(type, props, ...children) {
return {
type,
props: {
...props,
children: children.map(child =>
typeof child === "object" ? child : createTextElement(child)
),
},
};
}
function createTextElement(text) {
return {
type: "TEXT_ELEMENT",
props: {
nodeValue: text,
children: [],
},
};
}
Rendering the Virtual DOM to the Actual DOM
Next, we need a function to render our Virtual DOM to the actual DOM.
JavaScript
function render(element, container) {
const dom =
element.type === "TEXT_ELEMENT"
? document.createTextNode("")
: document.createElement(element.type);
const isProperty = key => key !== "children";
Object.keys(element.props)
.filter(isProperty)
.forEach(name => {
dom[name] = element.props[name];
});
element.props.children.forEach(child => render(child, dom));
container.appendChild(dom);
}
Reconciliation: Updating the Virtual DOM
To efficiently update the Virtual DOM, we’ll implement a simple reconciliation algorithm. This algorithm will diff the old Virtual DOM with the new one and update only the changed parts.
JavaScript
function updateElement(dom, prevProps, nextProps) {
Object.keys(prevProps)
.filter(isProperty)
.forEach(name => {
if (!nextProps.hasOwnProperty(name)) {
dom[name] = "";
}
});
Object.keys(nextProps)
.filter(isProperty)
.forEach(name => {
if (prevProps[name] !== nextProps[name]) {
dom[name] = nextProps[name];
}
});
}
Putting It All Together
Now, let’s create a function to reconcile our Virtual DOM with the actual DOM.
JavaScript
let nextUnitOfWork = null;
function performUnitOfWork(fiber) {
// TODO: perform work on the fiber
}
function workLoop(deadline) {
while (nextUnitOfWork) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
requestIdleCallback(workLoop);
}
requestIdleCallback(workLoop);
function commitRoot() {
// TODO: commit changes to the DOM
}
function render(element, container) {
nextUnitOfWork = {
dom: container,
props: {
children: [element],
},
};
}
Conclusion
Congratulations! You’ve just built a simple Virtual DOM from scratch using plain JavaScript. While this is a basic implementation, it demonstrates the fundamental concepts behind the Virtual DOM and how it can be used to optimize rendering in web applications.
Share your thoughts in the comments
Please Login to comment...