Home Web Front-end JS Tutorial Summary of vue's diff algorithm knowledge points

Summary of vue's diff algorithm knowledge points

May 28, 2018 am 11:26 AM
diff Summarize Knowledge points

This article shares with you a summary of relevant knowledge points about Vue’s diff algorithm. Friends who are interested can refer to it.

Virtual dom

The diff algorithm must first clarify the concept that the object of diff is the virtual dom, and updating the real dom is the result of the diff algorithm

Vnode base class

 constructor (
  。。。
 ) {
  this.tag = tag
  this.data = data
  this.children = children
  this.text = text
  this.elm = elm
  this.ns = undefined
  this.context = context
  this.fnContext = undefined
  this.fnOptions = undefined
  this.fnScopeId = undefined
  this.key = data && data.key
  this.componentOptions = componentOptions
  this.componentInstance = undefined
  this.parent = undefined
  this.raw = false
  this.isStatic = false
  this.isRootInsert = true
  this.isComment = false
  this.isCloned = false
  this.isOnce = false
  this.asyncFactory = asyncFactory
  this.asyncMeta = undefined
  this.isAsyncPlaceholder = false
 }
Copy after login

This part of the code is mainly to better understand the meaning of the specific diff attributes in the diff algorithm, and of course to better understand the vnode instance

Overall process

The core function is the patch function

  • isUndef judgment (whether it is undefined or null)

  • // empty mount (likely as component), create new root elementcreateElm(vnode, insertedVnodeQueue) Here you can find that creating nodes is not inserted one by one, but put into a queue for unified batch processing

  • Core function sameVnode

function sameVnode (a, b) {
 return (
  a.key === b.key && (
   (
    a.tag === b.tag &&
    a.isComment === b.isComment &&
    isDef(a.data) === isDef(b.data) &&
    sameInputType(a, b)
   ) || (
    isTrue(a.isAsyncPlaceholder) &&
    a.asyncFactory === b.asyncFactory &&
    isUndef(b.asyncFactory.error)
   )
  )
 )
}
Copy after login

Here is an outer comparison function that directly compares the key, tag (label), and data of two nodes ( Note that data here refers to VNodeData), and the type is directly compared for input.

export interface VNodeData {
 key?: string | number;
 slot?: string;
 scopedSlots?: { [key: string]: ScopedSlot };
 ref?: string;
 tag?: string;
 staticClass?: string;
 class?: any;
 staticStyle?: { [key: string]: any };
 style?: object[] | object;
 props?: { [key: string]: any };
 attrs?: { [key: string]: any };
 domProps?: { [key: string]: any };
 hook?: { [key: string]: Function };
 on?: { [key: string]: Function | Function[] };
 nativeOn?: { [key: string]: Function | Function[] };
 transition?: object;
 show?: boolean;
 inlineTemplate?: {
  render: Function;
  staticRenderFns: Function[];
 };
 directives?: VNodeDirective[];
 keepAlive?: boolean;
}
Copy after login

This will confirm whether the two nodes have further comparison value, otherwise they will be replaced directly

The replacement process is mainly a createElm function and the other is to destroy the oldVNode

// destroy old node
    if (isDef(parentElm)) {
     removeVnodes(parentElm, [oldVnode], 0, 0)
    } else if (isDef(oldVnode.tag)) {
     invokeDestroyHook(oldVnode)
    }
Copy after login

Insert To simplify the process, it is to determine the type of the node and call

createComponent respectively (it will determine whether there are children and then call it recursively)

createComment

createTextNode

After creation After using the insert function

, you need to use the hydrate function to map the virtual dom and the real dom

function insert (parent, elm, ref) {
  if (isDef(parent)) {
   if (isDef(ref)) {
    if (ref.parentNode === parent) {
     nodeOps.insertBefore(parent, elm, ref)
    }
   } else {
    nodeOps.appendChild(parent, elm)
   }
  }
 }
Copy after login

Core function

 function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
  if (oldVnode === vnode) {
   return
  }

  const elm = vnode.elm = oldVnode.elm

  if (isTrue(oldVnode.isAsyncPlaceholder)) {
   if (isDef(vnode.asyncFactory.resolved)) {
    hydrate(oldVnode.elm, vnode, insertedVnodeQueue)
   } else {
    vnode.isAsyncPlaceholder = true
   }
   return
  }

  if (isTrue(vnode.isStatic) &&
   isTrue(oldVnode.isStatic) &&
   vnode.key === oldVnode.key &&
   (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
  ) {
   vnode.componentInstance = oldVnode.componentInstance
   return
  }

  let i
  const data = vnode.data
  if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
   i(oldVnode, vnode)
  }

  const oldCh = oldVnode.children
  const ch = vnode.children
  if (isDef(data) && isPatchable(vnode)) {
   for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
   if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)
  }
  if (isUndef(vnode.text)) {
   if (isDef(oldCh) && isDef(ch)) {
    if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
   } else if (isDef(ch)) {
    if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, &#39;&#39;)
    addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
   } else if (isDef(oldCh)) {
    removeVnodes(elm, oldCh, 0, oldCh.length - 1)
   } else if (isDef(oldVnode.text)) {
    nodeOps.setTextContent(elm, &#39;&#39;)
   }
  } else if (oldVnode.text !== vnode.text) {
   nodeOps.setTextContent(elm, vnode.text)
  }
  if (isDef(data)) {
   if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
  }
 }
Copy after login

const el = vnode.el = oldVnode.el This is a very important step, let vnode.el refer to the current real dom. When el is modified, vnode.el will change synchronously.

  1. Compare whether the two references are consistent

  2. I don’t know what asyncFactory does after that, so I can’t understand this comparison

  3. Static node comparison key, no re-rendering will be done after the same, directly copy componentInstance (once command takes effect here)

  4. If vnode is a text node or comment node , but when vnode.text != oldVnode.text, you only need to update the text content of vnode.elm

  5. Comparison of children

  • If only oldVnode has child nodes, then delete these nodes

  • If only vnode has child nodes, then create these child nodes, here if oldVnode is a The text node sets the text of vnode.elm to the empty string

  • If both oldVnode and None of vnode has child nodes, but oldVnode is a text node or comment node, so set the text of vnode.elm to an empty string

  • updateChildren

This part focuses on the entire algorithmFirst four pointers, oldStart, oldEnd, newStart, newEnd, two arrays, oldVnode, Vnode.

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
  let oldStartIdx = 0
  let newStartIdx = 0
  let oldEndIdx = oldCh.length - 1
  let oldStartVnode = oldCh[0]
  let oldEndVnode = oldCh[oldEndIdx]
  let newEndIdx = newCh.length - 1
  let newStartVnode = newCh[0]
  let newEndVnode = newCh[newEndIdx]
  let oldKeyToIdx, idxInOld, vnodeToMove, refElm

  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
   if (isUndef(oldStartVnode)) {
    oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left
   } else if (isUndef(oldEndVnode)) {
    oldEndVnode = oldCh[--oldEndIdx]
   } else if (sameVnode(oldStartVnode, newStartVnode)) {
    patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
    oldStartVnode = oldCh[++oldStartIdx]
    newStartVnode = newCh[++newStartIdx]
   } else if (sameVnode(oldEndVnode, newEndVnode)) {
    patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
    oldEndVnode = oldCh[--oldEndIdx]
    newEndVnode = newCh[--newEndIdx]
   } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
    patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
    canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
    oldStartVnode = oldCh[++oldStartIdx]
    newEndVnode = newCh[--newEndIdx]
   } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
    patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
    canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
    oldEndVnode = oldCh[--oldEndIdx]
    newStartVnode = newCh[++newStartIdx]
   } else {
    if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
    idxInOld = isDef(newStartVnode.key)
     ? oldKeyToIdx[newStartVnode.key]
     : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
    if (isUndef(idxInOld)) { // New element
     createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
    } else {
     vnodeToMove = oldCh[idxInOld]
     if (sameVnode(vnodeToMove, newStartVnode)) {
      patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue)
      oldCh[idxInOld] = undefined
      canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
     } else {
      // same key but different element. treat as new element
      createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
     }
    }
    newStartVnode = newCh[++newStartIdx]
   }
  }
  if (oldStartIdx > oldEndIdx) {
   refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
   addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
  } else if (newStartIdx > newEndIdx) {
   removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
  }
 }
Copy after login

Several situations and processing of a loop comparison (the following - all refer to index -) The comparison is the node node of the comparison. The abbreviation is not rigorous and the comparison uses the sameVnode function, which is not true. Congruent

Conditions for the entire loop not to end oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx

##oldStart === newStart, oldStart newStart

  1. oldEnd === newEnd, oldEnd-- newEnd--

  2. oldStart === newEnd, oldStart Insert to the end of the queue oldStart newEnd--

  3. oldEnd === newStart, oldEnd is inserted into the beginning of the queue oldEnd-- newStart

  4. This is the only way to handle all the remaining situations. This kind of processing, after processing newStart

  5. newStart finds the same one in old, then move this to the front of oldStart
  • If you don't find the same one, create one and put it before oldStart

  • It is not completed after the loop ends

    There is still a period of judgment before it is complete
  • if (oldStartIdx > oldEndIdx) {
       refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
       addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
      } else if (newStartIdx > newEndIdx) {
       removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
      }
    Copy after login
    Simple What I mean is that after the loop ends, look at the contents between the four pointers, in the old array and in the new array, just back out more and make up less.

    The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.

    Related articles:

    Angular5 method of adding style class to the label of the component itself

    vue-cli development environment to implement cross-domain requests Method

    Detailed explanation of Vue-cli webpack mobile terminal automatic build rem problem

    The above is the detailed content of Summary of vue's diff algorithm knowledge points. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
1 months ago By 尊渡假赌尊渡假赌尊渡假赌
Two Point Museum: All Exhibits And Where To Find Them
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Python cheat sheet collection, what knowledge points have you mastered? Python cheat sheet collection, what knowledge points have you mastered? Apr 26, 2023 pm 10:49 PM

Python is currently the most popular programming language. I believe that a large number of novice friends will join the ranks of learning every day. However, no matter how easy a language is to learn, there are still many basic concepts and basic knowledge. For a novice, it is still difficult to master so many in one time. Today, we have collected many Python-related knowledge cheat sheets, which can be said to be all-inclusive. In the future, mom will no longer have to worry about everyone not being able to remember any knowledge points! Python basics Pythonbasics This cheat sheet contains all the basic knowledge of Python, from variable data types to list strings, from environment installation to the use of commonly used libraries, it can be said to be comprehensive. Beginner'sPytho

Summarize the usage of system() function in Linux system Summarize the usage of system() function in Linux system Feb 23, 2024 pm 06:45 PM

Summary of the system() function under Linux In the Linux system, the system() function is a very commonly used function, which can be used to execute command line commands. This article will introduce the system() function in detail and provide some specific code examples. 1. Basic usage of the system() function. The declaration of the system() function is as follows: intsystem(constchar*command); where the command parameter is a character.

Replace svn diff with vimdiff: a tool for comparing code Replace svn diff with vimdiff: a tool for comparing code Jan 09, 2024 pm 07:54 PM

Under Linux, it is very difficult to directly use the svndiff command to view code modifications, so I searched for a better solution on the Internet, which is to use vimdiff as a code viewing tool for svndiff, especially for those who are accustomed to using vim. It is very convenient. When using the svndiff command to compare the modifications of a certain file, for example, if you execute the following command: $svndiff-r4420ngx_http_limit_req_module.c, the following command will actually be sent to the default diff program: -u-Lngx_http_limit_req_module.c(revision4420)-Lngx_

Revealing the secret of HTML caching mechanism: essential knowledge points Revealing the secret of HTML caching mechanism: essential knowledge points Jan 23, 2024 am 08:51 AM

The secret of HTML caching mechanism: essential knowledge points, specific code examples are required In web development, performance has always been an important consideration. The HTML caching mechanism is one of the keys to improving the performance of web pages. This article will reveal the principles and practical skills of the HTML caching mechanism, and provide specific code examples. 1. Principle of HTML caching mechanism During the process of accessing a Web page, the browser requests the server to obtain the HTML page through the HTTP protocol. HTML caching mechanism is to cache HTML pages in the browser

Detailed explanation of MySQL data types: What you need to know Detailed explanation of MySQL data types: What you need to know Jun 15, 2023 am 08:56 AM

MySQL is one of the most popular relational database management systems in the world and is widely used because of its reliability, high security, high scalability and relatively low cost. MySQL data types define the storage methods of various data types and are an important part of MySQL. This article will explain in detail the data types of MySQL and some knowledge points that need to be paid attention to in practical applications. 1. MySQL data type classification MySQL data types can be divided into the following categories: Integer types: including TINYINT,

Oracle data types revealed: knowledge points you must know Oracle data types revealed: knowledge points you must know Mar 07, 2024 pm 05:18 PM

Oracle data types revealed: knowledge points you must understand and specific code examples required. Oracle, as one of the world's leading database management systems, plays an important role in data storage and processing. In Oracle, data type is a very important concept, which defines the storage format, range and operation method of data in the database. This article will reveal various knowledge points of Oracle data types and demonstrate their usage and characteristics through specific code examples. 1. Common data types character data types

Git workflow management experience summary Git workflow management experience summary Nov 03, 2023 pm 06:45 PM

Summary of Git workflow management experience Introduction: In software development, version management is a very important link. As one of the most popular version management tools currently, Git's powerful branch management capabilities make team collaboration more efficient and flexible. This article will summarize and share the experience of Git workflow management. 1. Introduction to Git workflow Git supports a variety of workflows, and you can choose the appropriate workflow according to the actual situation of the team. Common Git workflows include centralized workflow, feature branch workflow, GitF

Introduction to network security: What are the essential knowledge points for beginners? Introduction to network security: What are the essential knowledge points for beginners? Jun 11, 2023 am 09:57 AM

Introduction to network security: What are the essential knowledge points for beginners? In recent years, with the rapid development of the Internet, network security has attracted more and more attention. However, for many people, network security is still an unknown ocean. So, to get started with network security, what essential knowledge do beginners need to master? This article will sort it out for you. 1. Network attacks and threats First of all, understanding the types of network attacks and threats is a knowledge point that must be mastered to get started with network security. There are many types of cyber attacks such as phishing attacks, malware, ransomware

See all articles