Detailed explanation of virtual DOM and diff algorithm in react

Detailed explanation of virtual DOM and diff algorithm in react

The role of virtual DOM

First of all, we need to know what problem the emergence of virtual DOM is to solve. It solves the problem of low efficiency in our frequent direct DOM operations. So why is it so inefficient to directly manipulate the DOM?

For example, when we create a div, we can check in the console that this div has many properties that it has or inherits. Especially when we use js to operate DOM, our DOM itself is very complicated, and js operations will take a lot of time, but we cannot control the DOM elements themselves. Therefore, virtual DOM solves the problem of js operating DOM , which actually reduces the number of dom operations.

Simple implementation of virtual DOM

Virtual DOM, as the name suggests, is a fake DOM. Our real DOM is mounted on the page, while our virtual DOM is in memory. This requires us to abstract the real DOM into an object and store it in memory. This object can be of the following type:

var element = {
      tagName: 'div',
      props: {
        class: 'box'
      },
      children: {
        {
          tagName: 'p',
          props: {
            class: 'p1'
          },
          children: ['I am p1']
        }, 
         {
          tagName: 'p',
          props: {
            class: 'p2'
          },
          children: ['I am p2']
        }, 
        {
          tagName: 'p',
          props: {
            class: 'p3'
          },
          children: ['I am p3']
        },
      }
    }

If we want to construct such an object, we can encapsulate a constructor as follows:

function Element(tagName, props, children) {
    this.tagName = tagName
    this.props = props
    this.children = children
}

With this object, we need to render this virtual DOM to the real DOM. We can write the following method:

Element.prototype.render = function () {
    const { tagName, props, children } = this
    var el = document.createElement(tagName)
    for (key in props) {
        el.setAttribute(key, props[key])
    }
    children.forEach((item) => {
        const childEl = (item instanceof Element) ?
              item.render() :
        document.createTextNode(item)
        el.appendChild(childEl)
    })
    return el
}

Finally, we can create this object, call the render() method, and then appendChild to the body:

let virtualDom = new Element('div', { class: 'box' }, [
    new Element('p', { class: 'p1' }, ['I am p1']),
    new Element('p', { class: 'p2' }, ['I am p2']),
    new Element('p', { class: 'p3' }, ['I am p3']),
])

let a = virtualDom.render()
document.body.appendChild(a)

diff algorithm

First, let's understand the role of the diff algorithm

If our virtual DOM changes, a new virtual DOM will be generated in our memory. If we use this new virtual DOM structure directly, it will lead to a lot of repeated rendering. Therefore, the role of the diff algorithm is reflected at this time. Diff compares the new and old virtual DOM trees, finds the differences, records them, and then applies the recorded differences to the real DOM tree.

principle:

The diff algorithm performs a depth-first traversal of the new and old trees, adding a unique identifier to each node.

This process is divided into 2 steps

  • Find the differences between the two trees and record them in a pseudo-array.
  • Apply these differences to the actual DOM tree

The operations on DOM can be basically divided into 4 types

  • Deleting, moving, and adding child nodes to nodes
  • Change node labels
  • For text nodes, modify the node text
  • Modify node props

The following will roughly go through this process in the form of pseudo code

// diff function, compare two trees function diff(oldTree, newTree) {
    var patches = {}; // Pseudo array, record differences // Make error judgments for 4 types of nodes dfWork(oldTree, newTree, patches, index)

    return patches

}
function dfWork(oldTree, newTree, patches, index) {
    let currentPatch = []

    if (1) { // Delete the node currentPatch.push()
    } else if (3) { // Change the text of the node currentPatch.push()

    } else { // Modify the node's props Check children // Perform a diff algorithm on props and record the changes in patches.
        currentPatch.push({ type: patch.PROPS, props: propsPatches })
        // Then you need to perform a diff algorithm on the child nodes diffChildren(oldNode.children, newNode.children, index, patches, currentPatch)
    }
}
function diffChildren(oldChildren, newChildren, index, patches, currentPatch) {

    // Perform diff algorithm on child nodes, traverse child nodes, recursively call dfWork, and make differences to get patches

}
// Apply the changes to the actual DOM tree function patch(node, patches) {
    // node is the old DOM tree, patches changes.
    // We will traverse the patches and match the nodes to the patches.
}
function applyPatch(node, patches) {
    // Since each node may have multiple changes, we also need to traverse switch (patchs.type) {
        case REPLACE: // node replacement // node.render() 
            break;
        case REORDER: // Move, delete and add new child nodes.

            break;
        case PROPS:
            // setProps
            break;
        case TEXT: // Modify the node text // node.nodeValue
            break;

        default:
            break;
    }
}

Reference document: In-depth analysis: How to implement a Virtual DOM algorithm Author: livoras, built-in source code.

This is the end of this article about virtual DOM and diff algorithm in react. For more relevant react virtual DOM and diff algorithm content, please search previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Do you know the Diff algorithm in React?
  • In-depth analysis of the diff algorithm in React
  • React diff algorithm source code analysis
  • A brief discussion on analyzing the Diff algorithm from the React rendering process
  • Example implementation of React diff algorithm
  • React diff algorithm implementation ideas and principle analysis

<<:  Solution to the conflict between nginx and backend port

>>:  Detailed analysis of binlog_format mode and configuration in MySQL

Recommend

MySQL 5.7.16 ZIP package installation and configuration tutorial

This article shares the installation and configur...

The difference between char and varchar in MYSQL

CHAR and VARCHAR types are similar, differing pri...

MySQL sorting principles and case analysis

Preface Sorting is a basic function in databases,...

Solution to the horizontal scroll bar in iframe under IE6

The situation is as follows: (PS: The red box repr...

A brief discussion on the correct approach to MySQL table space recovery

Table of contents Preliminary Notes Problem Repro...

Command to view binlog file creation time in Linux

Table of contents background analyze method backg...

WeChat applet records user movement trajectory

Table of contents Add Configuration json configur...

Summary of commonly used SQL in MySQL operation tables

1. View the types of fields in the table describe...

How to use the EXPLAIN command in SQL

In daily work, we sometimes run slow queries to r...

vite2.x implements on-demand loading of ant-design-vue@next components

1. Use version vite:2.0 ant-design-vue: 2.0.0-rc....

HTML+CSS+jQuery imitates the search hot list tab effect with screenshots

Copy code The code is as follows: <!DOCTYPE ht...

Linux RabbitMQ cluster construction process diagram

1. Overall steps At the beginning, we introduced ...

How to prevent event bubbling in JavaScript

What we need to pay attention to is that the char...

Vue gets token to implement token login sample code

The idea of ​​using token for login verification ...