Open In App

Creating Your Own Virtual DOM Using JavaScript

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.

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.

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.

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.

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.

Article Tags :