Virtual DOM and DOM diff

Virtual DOM

Virtual DOM concept

Is a JavaScript object that represents a DOM tree and contains attributes tag, props, and children.

The virtual DOM was created to better render virtual nodes into the page view, so the nodes of the virtual DOM object correspond to the properties of the real DOM

<div id="app">
  <p class="text">hello world!!!</p>
</div>
Copy the code

The HTML above is converted to the virtual DOM as follows:

{
  tag: 'div'.props: {
    id: 'app'
  },
  chidren: [{tag: 'p'.props: {
        className: 'text'
      },
      chidren: [
        'hello world!!! ']]}}Copy the code

This object is often referred to as the virtual DOM, and because the DOM is a tree structure, it can be easily represented using JavaScript objects.

Advantages of virtual DOM
  • Reduce operating

    Multiple operations can be combined into one operation. For example, adding 1000 nodes does not have to be done one at a time. (Reduce times)

    DOM Diff is more flexible to manipulate. For example, if there are 90 nodes and you want to add 10 more nodes, simple JS cannot judge the new nodes and can only merge them into 100 nodes for adding. However, diff can determine 10 new nodes, which saves extra operations. (Reduced scope)

  • cross-platform

    The virtual DOM can become not only a DOM, but also applets, iOS apps, and Android apps, because the virtual DOM is essentially just a JS object

Disadvantages of virtual DOM

Additional creation functions, such as createElement or h, are required, but can be simplified to XML using JSX. The virtual DOM still crashes when the data is heavy, but the native DOM does not. In the case of nodes, the virtual DOM often crashes when 100,000 nodes are added.

DOM diff

DOM diff concept

Diff stands for different!

The diff algorithm, as the name suggests, compares the changes to the old and new VDOM and updates the changes to the view.

The principle of this change is as follows:

Think of it as a tree:

When we’re ready to delete the one with “hello”“, will become the following situation:

The way this works is that Diff changes “hello” to “world” and then removes the span with “world”. There were two steps.

Possible styles for DOM Diff
[{type: ‘INSERT’, vNode:... },// Insert the node
  {type: ‘TEXT’,  vNode:... },// Update the text
  {type: ‘PROPS’, propsPatch: [...]. }// Update attributes
]
Copy the code

Obviously, DOM Diff can save us a lot of operations, and its advantages are those of the virtual DOM.

DOM Diff’s logic

Tree diff

  • Compare the old and new trees layer by layer to find out which nodes need to be updated
  • If the node is a Component, see Component diff
  • If the node is a label, look at Element Diff

Component diff

  • If the node is a component, look at the component type first
  • Type different direct replacement (delete old)
  • If the type is the same, only the attribute is updated
  • And then go into the component and do Tree diff

Element diff

  • If the node is a native label, look at the label name
  • If the tag name is different, it is replaced. If the tag name is the same, only the attribute is updated
  • And then go into the tag descendant and do Tree diff
DOM diff problem

DOM Diff’s logic, while handy to use, has a flaw:

You can’t delete the one you want to delete without specifying the key attribute!

Example:

First, enter triangle, square, and circle in the three inputs. (No key attribute is placed here)

When we delete the square column

Oddly enough, the square is still a square, even though the two has been removed. Why is that?

As mentioned above, diff changes the square’s 2 to 3 and then removes the circle column.

To actually delete the square column, you must add a key.

We first add the array {1,2,3} to the attribute id, where id is our identifier as key, namely:

{ id: 1 }, { id: 2 }, {id: 3 }
Copy the code

The image looks like this:

Next we delete the square column:

And that’s it. That’s when the square doesn’t appear.

It is worth noting:

** We cannot use index as key. ** since index is continuous, if we delete 1 from 0,1, 2, then the order will become 0,1, not 1, 2. And that’s what we were talking about before: you can’t delete the person you want.