I’ve been looking into what DOM and shadow DOM are, and how they differ.
In summary, the Document Object Model (DOM) consists of two parts; One is an object-based representation of an HTML document, and the other is a set of interfaces that manipulate that object. The shadow DOM can be thought of as a reduced version of the DOM. It is also an object-based representation of HTML elements (recommend the magic Shadow DOM for better understanding) that separates the DOM into smaller bits and can be used across HTML documents.
Another term is “virtual DOM.” While this concept has been around for years, its use in the React framework is more popular. In this article, I’ll elaborate on what a virtual DOM is, how it differs from the original DOM, and how to use it.
Why do we need a virtual DOM?
To understand why the concept of the virtual DOM came into being, let’s revisit the original DOM. As mentioned above, the DOM has two parts — an object representation of an HTML document and a set of operation interfaces.
An: chestnut: :
<html lang="en">
<head></head>
<body>
<ul class="list">
<li class="list__item">List item</li>
</ul>
</body>
</html>
Copy the code
The above is an unordered list of only one piece of data, which can be converted to the following DOM object:
Suppose we want to change the contents of the first list item to “list item 1” and add a second list item. To do this, we need to use the DOM API to find the element we want to update, create a new element, add attributes and content, and finally update the DOM element itself.
const listItemOne = document.getElementsByClassName("list__item") [0];
listItemOne.textContent = "List item one";
const list = document.getElementsByClassName("list") [0];
const listItemTwo = document.createElement("li");
listItemTwo.classList.add("list__item");
listItemTwo.textContent = "List item two";
list.appendChild(listItemTwo);
Copy the code
The way we create web pages today was different from the first version of DOM in 1998, and they didn’t rely on the DOM API as much as we do today.
. For example, some simple methods such as document getElementsByClassName () can be used in small scale, but if updates per second many elements, it is very cost performance.
Further, because of the way the API is set up, updating large documents at once is more performance efficient than finding and updating specific documents. Chestnut:
const list = document.getElementsByClassName("list") [0];
list.innerHTML = `List item one List item two `;
Copy the code
Replacing the entire unordered list is better than modifying specific elements. In this particular case, chestnut:, the performance difference between the above two methods is likely to be negligible. However, as the size of the web grows, the difference becomes more apparent.
What is the virtual DOM?
The virtual DOM is created to update the DOM more efficiently and frequently. Unlike DOM or Shadow DOM, the virtual DOM is not an official specification, but rather a new way to interact with the DOM.
The virtual DOM is considered a copy of the original DOM. This copy can be manipulated and updated frequently without using the DOM API. Once all the updates to the virtual DOM have been made, we can see what specific changes need to be made to the original DOM, and finally make the changes in a targeted and optimized way.
The name “virtual DOM” tends to add to the actual mystique of the concept. In fact, the virtual DOM is just a regular Javascript object.
To review the previous DOM tree:
const vdom = {
tagName: "html".children: [{tagName: "head" },
{
tagName: "body".children: [{tagName: "ul".attributes: { "class": "list" },
children: [{tagName: "li".attributes: { "class": "list__item" },
textContent: "List item"
} // end li]}// end ul]}// end body]}// end html
Copy the code
Like the original DOM, it is an object-based representation of our HTML document. Because it’s a simple Javascript object, we can manipulate it freely and frequently without touching the real DOM.
You don’t have to use the entire object; it’s more common to use a small portion of the virtual DOM. For example, we can handle a list component, which will handle an unordered list element.
const list = {
tagName: "ul".attributes: { "class": "list" },
children: [{tagName: "li".attributes: { "class": "list__item" },
textContent: "List item"}};Copy the code
Principles of the virtual DOM
Now that we know what a virtual DOM is, how does it solve the performance problems of manipulating the DOM?
As I mentioned, we can use the virtual DOM to pick out the specific changes that need to be made to the DOM and make those specific updates separately. Go back to the example of the non-sequential representation and make the same changes using the virtual DOM.
The first thing we need to do is make a copy of the virtual DOM with the changes we want. We don’t need to use the DOM API, so we just create a new object.
const copy = {
tagName: "ul".attributes: { "class": "list" },
children: [{tagName: "li".attributes: { "class": "list__item" },
textContent: "List item one"
},
{
tagName: "li".attributes: { "class": "list__item" },
textContent: "List item two"}};Copy the code
This replica is used to create the so-called “difference” between the original virtual DOM (in this case, the list) and the updated virtual DOM. The difference might look something like this:
const diffs = [
{
newNode: { /* new version of list item one */ },
oldNode: { /* original version of list item one */ },
index: /* index of element in parent's list of child nodes */
},
{
newNode: { /* list item two */ },
index: { / * * /}}]Copy the code
The above objects provide the difference between the node data before and after the update. Once all the differences have been collected, we can batch change the DOM and make only the required updates.
For example, we can loop through each difference and add new children or update old children based on what Diff specifies.
const domElement = document.getElementsByClassName("list") [0];
diffs.forEach((diff) = > {
const newElement = document.createElement(diff.newNode.tagName);
/* Add attributes ... * /
if (diff.oldNode) {
// If there is an old version, replace it with the new version
domElement.replaceChild(diff.newNode, diff.index);
} else {
// If no old version exists, create a new nodedomElement.appendChild(diff.newNode); }})Copy the code
The framework
Using the virtual DOM through a framework is more common. Frameworks such as React and Vue use virtual DOM concepts to update the DOM more efficiently. For example, our list component can be written in React in the following manner.
import React from 'react';
import ReactDOM from 'react-dom';
const list = React.createElement("ul", { className: "list" },
React.createElement("li", { className: "list__item" }, "List item")); ReactDOM.render(list,document.body);
Copy the code
If we want to update the list, rewrite the entire list template and call reactdom.render () :
const newList = React.createElement("ul", { className: "list" },
React.createElement("li", { className: "list__item" }, "List item one"),
React.createElement("li", { className: "list__item" }, "List item two"); ; setTimeout((a)= > ReactDOM.render(newList, document.body), 5000);
Copy the code
Because React uses virtual DOM, even if we rerender the entire template, we only update the parts that actually differ.
conclusion
To review, the virtual DOM is a tool that allows us to interact with DOM elements in a simpler and more efficient way. It is a Javascript object representation of the DOM that we can modify as needed. The update is then optimal by collating all the changes made to the object and targeting the actual DOM.
The original link