Vue source learning (f) of the virtual DOM - DOM-Diff (on) Vue in

1 Introduction

In the previous article describes the VNodetime we said, VNodethe biggest purpose is to generate real change in the data before and after DOMthe virtual corresponding DOMnode, and then you can compare the two old and new VNode, to find out where the differences, there are differences then update DOMthe node, in order to reach the final minimum operating real DOMpurpose of updating the view. The contrast of old and new two VNodeand find out the differences of the process is called DOM-Diffprocess. DOM-DiffWhen the entire virtual algorithm DOMof the core, then the next, we start to source code, in-depth look at Vuethe DOM-Diffprocess is like.

2. patch

In the Vuemiddle, the DOM-Diffprocess is called patchprocess. patch, meaning "patch", referring to the old VNodepatch, patch resulting in a new VNode, very image of Kazakhstan. No matter what it is called, its essence is to compare the old and new two VNodeprocesses. We study the following patchwhen the process must grasp such an idea: the so-called old VNode(that is oldVNode) is the virtual before the data change view corresponding DOMnode, and the new VNodevirtual after data changes to be rendered new view corresponding DOMnode , so we need to generate a new VNodebasis, compared to the old oldVNode, if the new VNodeon some nodes and the old oldVNodeon not, then the old oldVNodeon add to; if the new VNodeon no node and the old oldVNodeon there , then in the old oldVNoderemoved on; if some nodes in the new VNodeand old oldVNodeon there, then a new VNodesubject, updating old oldVNode, so that new and VNodedifferent.

Maybe you feel a little bit around, it does not matter, we're talking plainly, you can interpret it this way: Suppose you have an old computer is now on the electronic version of the document, this time the boss gave you a new sheet of paper documents, and both of these documents tell you that most of the content is the same, so you fresh paper version of the document shall prevail, the paper version of the document to do a new electronic version of the document sent to the owner. For this task At this point, you should have two solutions: One option is whether it's an old document content is what, all deleted, and then knock against the new version of a paper document into a word by word, this program is no fee brain is tired by the point can solve the problem. While another program is based on the new paper version of the document as a benchmark, compared to the old look of the new electronic version of the document with the paper version of the document What are the differences, if there are certain parts in the new documentation and no documentation old , then put them together in the old part of the document inside; if certain parts of the document did not and the old in the new document in there, then delete these portions in the old documentation; if some parts of the old and the new documentation have, then compare to see if there needs to be updated, last updated look in the old document, reach the final version into the hands of the same with paper documentation, the perfect solution.

Contrast the above two schemes, and obviously you Vueas clever, will choose the second option. The second program in the electronic version of the old document that has been rendered on the corresponding view oldVNode, the new version of the document corresponding to the paper is to be rendered in the view of the new VNode. In a word: a new VNode basis, the transformation of the old oldVNode make it like new VNode, this is the patch process to do things .

Having said that, it sounds like a very complex feeling like, it is not true, we think about it, the whole patchis nothing more than doing three things:

  • Create a node: new VNodethere while the old oldVNodeis not, in the old oldVNodecreation.
  • To delete a node: new VNodeno old ones oldVNodehave it from the old oldVNodedeletion.
  • Update node: new VNodeand old oldVNodein both, with regard to a new VNodesubject, updating old oldVNode.

OK, here, you're right Vuein the patchprocess of understanding half, Next, we analyzed one by one, look Vuefor three things above all how to do.

3. Create a node

In the last article we analyzed, VNodethe class can be described six types of nodes, but in fact only three types of nodes can be created and inserted into the DOMmiddle, they are: element nodes, text nodes, comment nodes. So Vuewhen you create a node will determine the new VNodehave in the old oldVNodenot in this node is part of what type of nodes to invoke a different method to create and inserted into the DOMmiddle.

In fact, it is also difficult to determine, since it features three types of nodes is very evident in how to judge when the source:

// 源码位置: /src/core/vdom/patch.js
function createElm (vnode, parentElm, refElm) {
    const data = vnode.data
    const children = vnode.children
    const tag = vnode.tag
    if (isDef(tag)) {
        vnode.elm = nodeOps.createElement(tag, vnode)   // 创建元素节点
        createChildren(vnode, children, insertedVnodeQueue) // 创建元素节点的子节点
        insert(parentElm, vnode.elm, refElm)       // 插入到DOM中
    } else if (isTrue(vnode.isComment)) {
      vnode.elm = nodeOps.createComment(vnode.text)  // 创建注释节点
      insert(parentElm, vnode.elm, refElm)           // 插入到DOM中
    } else {
      vnode.elm = nodeOps.createTextNode(vnode.text)  // 创建文本节点
      insert(parentElm, vnode.elm, refElm)           // 插入到DOM中
    }
  }

From the above code, we can see:

  • Determining whether the element node simply determines VNodewhether the node has a tagtab. If there is tagproperty that is considered to be an element node, then call the createElementmethod creates an element node, usually there will be an element node child node, then recursively traverse all the child nodes created, all sub-nodes created after the good insertinto the current element node inside, finally current element node into DOMthe.
  • Determine whether the comment node, just judge VNodeof isCommentwhether the property is trueto, if it is truecompared to comment node, then call the createCommentmethod to create a comment node, and then inserted into the DOMmiddle.
  • If the node is neither an element nor comment nodes, it is considered a text node, then call the createTextNodemethod to create a text node, and then inserted into the DOMmiddle.

Code nodeOpsis Vueto cross-platform compatibility, all nodes operate the package, for example nodeOps.createTextNode()in the browser equivalent todocument.createTextNode()

This completes the operation of creating a node, the entire flow chart is as follows:

4. Delete Node

If some of the new node and then VNodeis not in the old oldVNodethere, then these need to nodes from the old oldVNodedeletion. Delete nodes is very simple, just call on the parent element to be deleted node removeChildmethod can be. Source as follows:

function removeNode (el) {
    const parent = nodeOps.parentNode(el)  // 获取父节点
    if (isDef(parent)) {
      nodeOps.removeChild(parent, el)  // 调用父节点的removeChild方法
    }
  }

5. Update node

Creating nodes and delete nodes are relatively simple, and update the node is relatively more complicated, but in fact is not too much complicated, just sort out the logic will be able to understand.

Updates node is when some of the nodes in the new VNodeand the old oldVNodein there, we need to carefully compare, find a different place to be updated.

Before we update the node, we first introduce the concept of a small, static node is what? We look at an example:

<p>我是不会变化的文字</p>

Above this node which contains only the text, without any variable variables, which means that, regardless of the data and then how changes, as long as the node for the first time rendering, and then later on it will never change, because it does not contain any variable, so any changes in the data occur nothing to do with it. We call this node is called a static node.

OK, with this concept we were beginning to update the node. When we need to update the node judges the following three cases and dealt with separately:

  1. If VNodeand oldVNodeare static nodes

    We say, static node data regardless of any change has nothing to do with it, so are static node, then skip directly without treatment.

  2. If VNodea text node

    If VNodea text node that is represented in this node contains only plain text, you can simply look at oldVNodewhether it is a text node, and if so, whether it is to compare two different text, different if put oldVNodein the text into with VNodethe text the same. If oldVNodenot a text node, then no matter what it is, a direct call setTextNodemethod turning it into text nodes and text content with VNodethe same.

  3. If VNodeis an element node

    If VNodeis an element node, then subdivided the following two situations:

    • The node has children

      If you include the child nodes within the new node, then the time to look at the old node contains child nodes, if a node in the old also contains a child node, it needs updating child nodes recursively contrast; if the old node is not included in child node, then the old node there may be empty node or text node, if the old node is an empty node new node to put in the child node creates a node is then inserted into the inside of the old, if the old node is text node, put the empty text, and then create a new child node node in a node is then inserted into the old inside.

    • The node has no child node

      If the node does not contain child nodes, while it is not a text node, it shows that the node is an empty node, it is easy to handle, there are no matter what's before the old node, can be emptied directly.

OK, finished with more than three cases, the basic completion of the update even if a node, then we look at is how to achieve specific source, the source code is as follows:

// 更新节点
function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
  // vnode与oldVnode是否完全一样?若是,退出程序
  if (oldVnode === vnode) {
    return
  }
  const elm = vnode.elm = oldVnode.elm

  // vnode与oldVnode是否都是静态节点?若是,退出程序
  if (isTrue(vnode.isStatic) &&
    isTrue(oldVnode.isStatic) &&
    vnode.key === oldVnode.key &&
    (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
  ) {
    return
  }

  const oldCh = oldVnode.children
  const ch = vnode.children
  // vnode有text属性?若没有:
  if (isUndef(vnode.text)) {
    // vnode的子节点与oldVnode的子节点是否都存在?
    if (isDef(oldCh) && isDef(ch)) {
      // 若都存在,判断子节点是否相同,不同则更新子节点
      if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
    }
    // 若只有vnode的子节点存在
    else if (isDef(ch)) {
      /**
       * 判断oldVnode是否有文本?
       * 若没有,则把vnode的子节点添加到真实DOM中
       * 若有,则清空Dom中的文本,再把vnode的子节点添加到真实DOM中
       */
      if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
      addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
    } 
    // 若只有oldnode的子节点存在
    else if (isDef(oldCh)) {
      // 清空DOM中的子节点
      removeVnodes(elm, oldCh, 0, oldCh.length - 1)
    } 
    // 若vnode和oldnode都没有子节点,但是oldnode中有文本
    else if (isDef(oldVnode.text)) {
      // 清空oldnode文本
      nodeOps.setTextContent(elm, '')
    }
    // 上面两个判断一句话概括就是,如果vnode中既没有text,也没有子节点,那么对应的oldnode中有什么就清空什么
  } 
  // 若有,vnode的text属性与oldVnode的text属性是否相同?
  else if (oldVnode.text !== vnode.text) {
    // 若相同:用vnode的text替换真实DOM的文本
    nodeOps.setTextContent(elm, vnode.text)
  }
}

The above code comments have been written very clearly, and then we draw a flow chart to sort out the whole process flow chart is as follows:

By shining a flowchart and code, I believe that part of the logic node update you can easily understand.

In addition, you may have noticed, if the old and new VNodein the child nodes are included, then for updating child nodes in the code calls updateChildrenthe method, and the logic of this approach in the end is what we put next article expand learning.

6. Summary

In this article we introduced Vuethe DOM-Diffalgorithm: patch process. We first introduced the idea of the whole process algorithm, then combing through algorithm, to understand the whole patchprocess did three things, namely: to create nodes, delete nodes, updated nodes. And a control source for everything launched a detailed study, which depicts the logic flow diagram. In addition to updating node, if the old and new VNodein the child nodes are included, we need to update the detailed sub-nodes on the process of updating child nodes we started to learn in the next article.
(Finish)

Guess you like

Origin www.cnblogs.com/wangjiachen666/p/11846299.html