This is the 7th day of my participation in Gwen Challenge.

preface

The core part of the virtual DOM is patch, which can render the VNode into the real DOM.

Patch itself means patch, patch, etc. Its actual function is to modify the current DOM to achieve the purpose of updating the view.

introduce

Comparing the differences between two VNodes is only part of the patch, it’s the means, not the end. The purpose of patch is to modify DOM nodes. To make changes to the existing DOM, you need to do three things:

  1. Create a new node
  2. Delete an obsolete node
  3. Modify the node to be updated

The process of patch is actually the process of creating nodes, deleting nodes and modifying node pairs.

The new node

If a node already exists in the DOM, there is no need to create an identical node to replace the existing node. We need to create a node to insert into the DOM only if the new node is not already in the DOM due to the state change.

[vnode] -- > graph LR v e o [oldVnode] -. - e e element [] -- > w [view]

When rendering a view for the first time, use vNode to render the view directly.

Remove nodes

Nodes that do not exist in a VNode are discarded nodes, which need to be deleted from the DOM.

Update the node

New nodes and deleted nodes have one thing in common – the two virtual nodes are completely different.

A more common scenario is that the old and new nodes are the same node, and we need to compare the two nodes carefully before updating the view.

summary

The main flow of patch

Graph p([patch]) --> o{oldVnode <br /> exists} o --> I ([create <br /> node with vNode and insert view]) o --> s{oldVnode <br /> and vNode exist <br /> Is it the same node as <br />} s -- yes --> U ([Patchvnode <br /> for more detailed <br /> comparison and update operation]) s -- no --> r[Using vnode to create real node <br /> Insert into view next to node] r --> d([delete old node in view])

Create a node

There are only three types of nodes in vue.js that are created and inserted into the DOM:

  • Element nodes
  • Comment node
  • Text node

We can call document.createElement to create the actual element node and parentnode. appendChild to insert the element node into the specified parentNode.

Normally, element nodes have children, so when an element node is created, we need to create its children and insert them under the newly created node.

Graph (c [create node]) - > e [create element node] -- > cc] [create child node - > I ([insert into parentNode])

In addition to element nodes, we can also create comment nodes and text nodes.

If a VNode does not have a tag attribute, we can use the isComment attribute to determine whether it is a comment node or a text node. If it is a text node, call the document.createTextNode method to create the text node. If it is a comment node, call the document.createcomment method to create the comment node.

Graph s([create node]) --> s1{vnode is an element node? } -- -- -- > c [create element node] -- > e ([insert to specify the parent node]) s1 - no - > s2 {vnode is a comment node? } -- -- -- > cc/create a comment node - > s2 - n - e > ct [] create a text node - > e

Figure: The process from creating a node to rendering a view

Remove nodes

There is not much code in vue.js to remove nodes.

function removeVnodes(vnodes, startIdx, endIdx){
    for(; startIdx <= endIdx; ++startIdx){
        const ch = vnodes[startIdx];
        if (isDef(ch)){
            removeNode(ch.elm)
        }
    }
}
Copy the code

RemoveNode implementation logic:

const nodeOps = {
    removeChild(node, child){
        node.removeChild(child)
    }
}

function removeNode(el){
    const parent = nodeOps.parentNode(el);
    if (isDef(parent)){
        nodeOps.removeChild(parent, el)
    }
}
Copy the code

For cross-platform purposes, put node operations in nodeOps.

Update the node

Static node

What is a static node?

Static nodes are those that, once rendered to the interface, do not change no matter how their state changes.

Such as:

<p>This is a static node</p>
Copy the code

Therefore, when the old and new virtual nodes are static, you can skip the node update process.

The new virtual node has text attributes

If the newly generated virtual node has a text attribute, call setTextContent directly to change the content of the DOM node in the view to the text held by the text attribute.

The new virtual node has no text attribute

Have the children

  1. Old virtual nodes also have children, calledupdateChildrenFor more detailed comparison, the specific will be analyzed later.
  2. The old virtual node has no children, indicating that the old virtual node is either an empty label or a text node with text. So if it is a text node, empty the text first, and then create the children of the new virtual node into the real DOM node in turn.

No children

If the new virtual node has neither text nor children attribute, it is an empty label, so simply empty the text and children attribute of the old virtual node.

summary

Graph s([update node]) --> a{vnode and oldVnode <br> exactly equal} -- yes --> b([exit program]) --> c{vnode and oldVnode <br> are static nodes} -- Yes --> b([exit program]) c -- no --> e{vnode has text attribute? } --> f{vnode <br> text and oldVnode <br> text is the same? } f -- same -->b f -- different --> text -->b e -- no --> g{vnode has <br> child nodes? } g -- no --> h{oldVnode<br> has child nodes? } h - - - > I ([empty < br > child node in the DOM]) h - no - > j {oldVnode < br > text? } - > k (empty [text] in the DOM) g - - - > {l oldVnode < br > have child nodes? {} l - - - > m oldVnode child node < br > < br > and vnode child node is not the same} -- -- -- > n (/ update child nodes) l - no - > o {oldVnode < br > text? } - - - > p/empty DOM text > q o -- no -- - > q ([the vnode child nodes are added to the DOM])

Update child Nodes

In most cases, not all child nodes move, and there are always some nodes in a list that remain the same.

For this purpose, vue.js references the diff algorithm of snabbDOM’s two-end comparison. To avoid looping oldChildren to find a node, four quick lookups are provided:

  • The old and the new
  • New queen and old queen
  • The new queen and the old one
  • New before and old after

Explain the four nouns:

  • New before: The first unprocessed node in newChildren
  • New after: The last unprocessed node in newChildren
  • Old before: The first unprocessed node in oldChildren
  • After old: The last unprocessed node in oldChildren

The old and the new

If the new node and the old node are the same, you do not need to move the node. You can directly update the node. If not, use the new to compare with the old.

New queen and old queen

If the new post is the same as the old one, the node is also updated. If not, compare the new with the old.

The new queen and the old one

If the new node is the same node as the old one, because they are in different positions, in addition to updating the node, you need to move the node to the end of all unprocessed nodes in oldChildren.

New before and old after

Similar to the above, in addition to updating the node, you need to move the node to the front of all unprocessed nodes in oldChildren.

summary

In the above procedure, if oldChilren traverses first, the unprocessed nodes in newChildren are the nodes that need to be added. Conversely, if newChildren traverses first, the unprocessed nodes in oldChildren are the nodes that need to be deleted.

If all the above four look-ups are checked, it is found that none of oldChildren and newChildren has traversed all the child nodes, indicating that there may be some reusable nodes that are not continuous in the remaining nodes. At this point, we need to loop oldChildren to establish the corresponding relationship between node key and index index.

Here comes the big test!

Why is key recommended?

Use keys unless your list of child nodes is simple or you want to use the default principle of in-place reuse for efficiency. The obvious advantage of using key is that if the above situation occurs, the reusable nodes are not continuous or are disrupted. In this case, we can quickly find the nodes we need to compare from oldChildren through the corresponding relationship between key and index index.

conclusion

In this paper, we learned the patch of vue.js together.

  • How to update old and new nodes;
  • How to use diff algorithm of double – end comparison to update child nodes.