The beginning of the controversy

It all started in the fall of 2013.

This is actually pretty fast, mainly because most DOM operations tend to be slow. There’s a lot of performance work going on in the DOM, but most DOM operations drop frames.

Right! This is the picture, which leads you into the idea that DOM manipulation is expensive and slow, and Virtual DOM is fast.

Six years later, React has become popular all over the world, and Virtual DOM has been recognized by everyone. The Chinese star VUE also uses Virtual DOM.

So is Virtual DOM really fast? What exactly does the Virtual DOM mean? Why do we use the Virtual DOM?

We’ve all heard that updating the Document Object Model (DOM) directly is inefficient and slow. But few of us actually have the data to back it up. The talk about the React virtual DOM is that it’s a more efficient way to update views in Web applications, but few of us know why and if this efficiency leads to faster page rendering times.

Aside from the other benefits of using React, such as one-way data binding and components, I’ll discuss what the Virtual DOM really is and whether it justifies React over other UI libraries (or none at all).

Why do we need a UI library

Why do we need a UI library?

I’m sure that in today’s front-end world, a large percentage of people don’t know what to do outside of the big three frameworks. They may take it for granted that views and data are bound (VUE), or simply use setState to update views (React).

With the UI library, we can directly bind the data to the view without having to manipulate the DOM.

Why don’t we want to manipulate DOM

I won’t go into DOM in detail here, I’ll just skim over it.

DOM stands for document Object Model and is an abstraction of structured text. For Web developers, this text is HTML code, DOM for short *HTML DOM. HTML elements become nodes * in the DOM.

The HTML DOM provides an interface (API) for traversing and modifying nodes. It contains methods like getElementById or removeChild. We usually use the JavaScript language to process the DOM because…… Well, no one knows why :).

So whenever we want to dynamically change the content of a web page, we modify the DOM:

var item = document.getElementById("myLI");
item.parentNode.removeChild(item);
Copy the code

Document is an abstraction of the root node, getElementById, parentNode, and removeChild are methods from the HTML DOM API.

The problem is, since the HTML DOM is always a tree structure, we can easily traverse each node, but nowadays in Web apps, DOM trees are getting bigger and bigger, and we need to constantly modify a lot of DOM trees. This is where it really hurts.

We usually update the DOM with one of the following processes:

  1. Traverse (or use id) the tree to find the relevant node
  2. Update this node as necessary

There are obviously several problems with this:

  1. It’s hard to manage. Find a node and analyze the context of the relationship, time and energy, accidentally like mentionbug.
  2. Very inefficient.

Why is updating the DOM slow

Updating the DOM is not slow, just like updating any JavaScript object.

So what makes updating the real DOM slow?

Is drawn.

Drawing takes up most of the time in layout.

As you can see from the following figure and this article, the real problem with updating the DOM is screen drawing.

The rendering engine, which is responsible for displaying or rendering the web page on the browser screen, parses the HTML page to create the DOM. It also parses CSS and applies it to HTML to create a rendering tree, a process called ** Attachment **.

So, when we do this

document.getElementById('elementId').innerHTML="New Value"
Copy the code

The following happens:

  1. Browsers must parseHTML
  2. It removes theelementIdThe child elements
  3. Update with “New Value”DOM
  4. Recalculate parent and childCSS
  5. Update the layout, the exact coordinates of each element on the screen
  6. Traverse the render tree and draw it on the browser display

Recalculating CSS and changing layouts use complex algorithms that can affect performance.

Thus, updating the real DOM involves not just updating the DOM, but many other processes.

Furthermore, each of the above steps runs for each update of the real DOM, meaning that if we update the real DOM 10 times, each of the above steps will be repeated 10 times. This is why updating the DOM is slow.

The magic of Virtual DOM

First, React didn’t invent the Virtual DOM, but React uses it and makes it available for free.

Due to the complexity of DOM operation, Virtual DOM is created. It is stored in memory in the state of a Virtual tree, and then mapped to the real DOM. Each update is the comparison of Virtual trees, and then the difference part is updated and reflected to the real DOM. This reduces the need to manipulate the real DOM.

The virtual DOM is faster to update in React because React uses it

  1. Efficient diff algorithm
  2. Batch batching operation
  3. Only the subtree is effectively updated
  4. Use observable (observable) instead of a dirty check to detect changes

AngularJS uses dirty checking to find changed models. The dirty check process runs in a loop after a specified time. As the application grows, examining the entire model degrades performance, which slows the application down.

Every time the setState() method is called, ReactJS creates the entire Virtual DOM from scratch. Creating the whole tree is very fast, so there is no performance impact.

At any given time, ReactJS maintains two Virtual DOM, one with the updated state Virtual DOM and one with the previous state Virtual DOM.

Compare the Virtual DOM using the Diff algorithm to find and update to the Real DOM.

For example, first our state.subject value is world:

<div> <div id="header"> <h1>Hello, {{state.subject}}! </h1> <p>How are you today? </p> </div> </div>Copy the code

The parsed Virtual DOM can be expressed as:

{
  tag: 'div'.children: [{tag: 'div'.attributes: {
        id: 'header'
      },
      children: [{tag: 'h1'.children: 'Hello, World! '
        },
        {
          tag: 'p'.children: 'How are you today? '}]}]}Copy the code

Now, with the value of state.subject changed to Mom, the rendered Virtual DOM is:

{
  tag: 'div'.children: [{tag: 'div'.attributes: {
        id: 'header'
      },
      children: [{tag: 'h1'.children: 'Hello, Mom! '
        },
        {
          tag: 'p'.children: 'How are you today? '}]}]}Copy the code

After the diff algorithm, it is determined that only the h1 element is updated, and then the updated element is mapped to the DOM to complete the update.

As for the Batching and Diff algorithms, they have a large amount of content, so we need to open another blog to talk about them. At present, there are many explanations available, so you can search for them.

Is Virtual DOM really faster than directly manipulating DOM

Every article and article on the Virtual DOM points out that while today’s JavaScript engines are very fast, reading and writing the browser’s DOM is slow.

That’s not quite right. DOM soon. Adding and removing DOM nodes is not much slower than setting properties on JavaScript objects. This is just a simple operation.

Here’s an example:

Here’s a way to render using native DOM:


      
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello JavaScript!</title>

</head>
<body>
<div id="example"></div>
<script>
    document.getElementById("example").innerHTML = "

Hello, world!

"
;
</script> </body> </html> Copy the code

Here’s one way to implement React:


      
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="build/react.js"></script>
    <script src="build/react-dom.js"></script>
</script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
    ReactDOM.render(
    <h1>Hello, world!</h1>.document.getElementById('example'));</script>
</body>
</html>
Copy the code

Rendering time required to use native:

React takes time to render:

At first glance, native rendering is much faster than React.

One thing we missed was the small amount of data on the page. This might be reasonable in the case of a large list where all the data changes, but it would be wasteful to reset the entire innerHTML if only one row of data changes.

Comparing innerHTML with the Virtual DOM redrawing process is as follows:

  • innerHTML: render HTML string ==> re-creates all DOM elements
  • Virtual DOM: render Virtual DOM ==> diff ==> Necessary DOM updates

Js computation is very cheap compared to DOM manipulation. Virtual DOM Render + diff is obviously slower than rendering HTML strings, but it’s still pure JS level computation, and it’s still much better than the DOM manipulation behind it.

The layout that the browser must perform when the DOM changes. Every time the DOM changes, the browser needs to recalculate the CSS, lay it out, and redraw the page, which takes a lot of time.

Browser manufacturers are constantly trying to reduce the time it takes to redraw screens, and the biggest thing that can be done is to minimize and batch DOM changes.

This strategy of reducing and batching DOM changes, which takes another level of abstraction, is the idea behind React’s Virtual DOM.

The last

React never says that React is faster than the native DOM operation. React gives us the assurance that it still gives us decent performance without the need for manual tuning.

React masks the underlying DOM manipulation and allows us to describe our purposes in a more declarative way, making our code easier to maintain.

No framework can be faster than purely manual DOM optimization operations, because the framework’s DOM manipulation layer needs to handle any operations that may be generated by the upper API, and its implementation must be universal. I can write manual optimizations faster than any framework for any benchmark, but what’s the point? When building a real application, do you manually optimize everything? This is obviously not possible for maintainability reasons.

Finally, I want to promote the component library I wrote based on the Taro framework: MP-Colorui.

I will be very happy if I can star easily. Thank you.

Click here for documentation

Click here to get the GitHub address