An in-depth analysis of the Diff algorithm in Vue2
The diff algorithm is an efficient algorithm that compares tree nodes at the same level, avoiding the need to search and traverse the tree layer by layer. So how much do you know about the diff algorithm? The following article will give you an in-depth analysis of the diff algorithm of vue2. I hope it will be helpful to you!
Because I often asked about the Diff algorithm when watching live interviews before, and the author himself uses Vue2 a lot, so I plan to study the Diff algorithm of Vue2. In fact, I have wanted to learn it for a long time. Yes, but maybe because I feel that the Diff algorithm is relatively profound, I have been putting off learning it. But recently I was preparing for an interview, so I thought I would learn it sooner or later. Why not take this opportunity to understand the Diff algorithm? The author spent a day on it. After some research, I may not fully understand the essence of the Diff algorithm. Please forgive me.
? This actually counts as the author's study notes, and the author's level is limited. The revised article only represents the author's personal opinion. If there are any errors, you can point them out in the comment area and they will be continuously improved. At the same time, this article is very long, so Readers, please read it patiently. After reading this, the author believes that you will have a deeper understanding of the Diff algorithm. I think this article is better than most of the articles on the Internet currently explaining the Diff algorithm, because this article starts from the problem and teaches everyone how to think, rather than starting directly from the answer, just like reading the answer, which feels meaningless. This article explains step by step Guide everyone to feel the subtlety of the Diff algorithm. At the same time, we also conducted a small experiment to give everyone a more intuitive experience of the Diff algorithm.
Why use Diff algorithm
Virtual DOM
Because the bottom layer of Vue2 uses virtual DOM to represent the page Structural, virtual DOM is actually an object. If you want to know how to generate it, the general process is:
- First parse the template string, which is
.vue
file - Then convert it into an AST syntax tree
- Then generate the render function
- Finally call the render function to generate a virtual DOM [Related recommendations: vuejs video tutorial, Web front-end development】
Minimum update
In fact, the framework only uses virtual DOM for performance, because js generates DOM and then displays it Pages consume a lot of performance. If the entire page is regenerated every time it is updated, the experience will definitely not be good. Therefore, you need to find the changes in the two pages, and then just update the changed places with js(possibly Whether it is adding, deleting or updating) It only takes one click, which is the minimum amount of updates. So how to achieve the minimum amount of updates? Then we need to use the Diff algorithm. So what exactly does the Diff algorithm compare? Maybe this is where it is easy to misunderstand the Diff algorithm when you first learn it. In fact, it compares the old and new virtual DOM, so the Diff algorithm is to find the difference, find the difference between the two virtual DOMs, and then reflect the difference to On the page, this achieves the smallest amount of updates. If only the changed places are updated, the performance will definitely be better.
Page update process
In fact, this is more difficult to explain. The author will give a rough introduction. Anyone who has learned Vue knows that one of the characteristics of this framework is data response. What is responsive style, that is, the page is also updated when the data is updated, so how does the page know that it needs to be updated? In fact, this is the clever part of this framework. The general process is as follows:
- As mentioned before, the render function will be run, so when the render function is run, the data will be hijacked, that is, entering
Object.defineProperty
'sget
, then dependencies are collected here, then who collects dependencies? It is each component. Each component is a Watcher, which will record all the variables (that is, dependencies) in this component. Of course, each dependency (Dep) will also collect its own location. Watcher of the component; - Then when the data in the page changes, the
set
ofObject.defineProperty
will be triggered. In this function, the data will notify everyone A Watcher updates the page, and then each page will call the update method. This method ispatch
; - Then, you need to find the amount of change between the two pages, then you need to use Let’s go to the Diff algorithm
- After finally finding the change amount, we can update the page
In fact, we update while searching. In order to make it easier for everyone to understand, these two Parts are separated
A brief introduction to the Diff algorithm
When asked in an interview what the Diff algorithm is, everyone will definitely say a few words, such as 头头, tail tail, tail head, head Tail
, Depth-first traversal (dfs)
, Comparison of the same layer
Similar to these words, although I can say one or two sentences, it is just a taste.
In fact, the author read an article about the Diff algorithm published on CSDN, which is a highly read article. The author feels that he did not understand it clearly. Maybe he did not understand it himself, or he understood it but did not explain it clearly. Then the author will use his own Let me share my insights with you.
The premise of Diff algorithm
In order for everyone to understand clearly, here is the function calling process:
- patch
- patchVnode
- updateChildren
Diff algorithmPrerequisite
This is very important. You may ask what is the premise? Isn't it just the comparisons mentioned before? It's true but it's also wrong, because the Diff algorithm reaches the head, tail, tail, head, tail
mentioned before. The premise of this step is that the nodes compared twice are the same
, the similarity here is not exactly the same as everyone thinks, but it is the same if it meets certain conditions. To simplify the explanation, the article only considers one tag that only contains key
and tag name (tag)
, then what I said before is that the key is the same and the tag is the same
. In order to prove that the author's statement is somewhat correct, the source code is also posted here:
// https://github.com/vuejs/vue/blob/main/src/core/vdom/patch.ts // 36行 function sameVnode(a, b) { return ( a.key === b.key && a.asyncFactory === b.asyncFactory && ((a.tag === b.tag && a.isComment === b.isComment && isDef(a.data) === isDef(b.data) && sameInputType(a, b)) || (isTrue(a.isAsyncPlaceholder) && isUndef(b.asyncFactory.error))) ) }
If you are afraid of confusion, the following You can omit it and it won’t affect the overall understanding. The following is just a judgment added to consider all situations: So if the two virtual DOMs are not the same, there is no need to continue to compare, and if they are the same, there is no need to compare. The similarity here is really exactly the same, that is, the addresses of the two virtual DOMs are the same, so also paste the source code:
function patchVnode(......) { if (oldVnode === vnode) { return } ...... }
So far everyone may be confused, now let’s summarize:
- What is compared in the
patch
function is whether the old and new virtual DOM iskey is the same and tag is the same
. If they are not the same, just replace them directly. If they are the same, usepatchVnode
. Having said so much, the author actually wants to express a point. , that is, the Diff algorithm will be considered only when the two compared virtual DOMs are the same
. If they are not consistent, just delete the original one and replace it with the new DOM.
patchVnode function
What is in this function is the real Diff algorithm, so I will introduce it to you based on the source code.
The core code in the source code is from line 638 to line 655 of patch.ts.
In fact, the current introduction of patchVnode is directly introduced to the source code, but you may not know why it is classified in this way, so the author is here to let you understand why it is classified in this way. First of all, Here is a conclusion:
- is the
text
attribute and thechildren
attribute cannot exist at the same time. This requires everyone to look at the template parsing source code part
Then when comparing old and new nodes, the main comparison is whether there are text
and children
, then there will be the following nine situations
Situation | Old node text | Old node children | New node text | New node children | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | ❎ | ❎ | ❎ | ❎ | ||||||||||||||||||||||||||||||||
2 | ❎ | ✅ | ❎ | ❎ | ||||||||||||||||||||||||||||||||
✅ | ❎ | ❎ | ❎ | |||||||||||||||||||||||||||||||||
❎ | ❎ | ❎ | ✅ | |||||||||||||||||||||||||||||||||
❎ | ##✅❎ | ✅ | 6 | |||||||||||||||||||||||||||||||||
❎ | ❎ | ✅ | 7 | |||||||||||||||||||||||||||||||||
❎ | ✅ | ❎ | 8 | |||||||||||||||||||||||||||||||||
✅ | ✅ | ❎ | 9 | |||||||||||||||||||||||||||||||||
❎ | ✅ | ❎ |
实验 | 没有 key | key 为 index | key 唯一 |
---|---|---|---|
在队尾增加 | 1 | 1 | 1 |
在队中增加 | n - i + 1 | n - i + 1 | 1 |
在队首增加 | n + 1 | n + 1 | 1 |
删除实验
表格为每次实验中,每种情况的最小更新量,假设列表原来的长度为 n
实验 | 没有 key | key 为 index | key 唯一 |
---|---|---|---|
在队尾删除 | 1 | 1 | 1 |
在队中删除 | n - i | n - i | 1 |
在队首删除 | n | n | 1 |
通过以上实验和表格可以得到加上 key 的性能和最小量更新的个数是最小的,虽然在 在队尾增加
和 在队尾删除
的最小更新量相同,但是之前也说了,如果没有 key 是要循环整个列表查找的,时间复杂度是 O(n),而加了 key 的查找时间复杂度为 O(1),因此总体来说加了 key 的性能要更好。
写在最后
本文从源码和实验的角度介绍了 Diff 算法,相信大家对 Diff 算法有了更深的了解了,如果有问题可私信交流或者评论区交流,如果大家喜欢的话可以点赞 ➕ 收藏 ?
源码函数附录
列举一些源码中出现的简单函数
setTextContent
function setTextContent(node: Node, text: string) { node.textContent = text }
isUndef
function isUndef(v: any): v is undefined | null { return v === undefined || v === null }
isDef
function isDef<T>(v: T): v is NonNullable<T> { return v !== undefined && v !== null }
insertBefore
function insertBefore( parentNode: Node, newNode: Node, referenceNode: Node ) { parentNode.insertBefore(newNode, referenceNode) }
nextSibling
function nextSibling(node: Node) { return node.nextSibling }
createKeyToOldIdx
function createKeyToOldIdx(children, beginIdx, endIdx) { let i, key const map = {} for (i = beginIdx; i <= endIdx; ++i) { key = children[i].key if (isDef(key)) map[key] = i } return map }
The above is the detailed content of An in-depth analysis of the Diff algorithm in Vue2. For more information, please follow other related articles on the PHP Chinese website!

WhentheVue.jsVirtualDOMdetectsachange,itupdatestheVirtualDOM,diffsit,andappliesminimalchangestotherealDOM.ThisprocessensureshighperformancebyavoidingunnecessaryDOMmanipulations.

Vue.js' VirtualDOM is both a mirror of the real DOM, and not exactly. 1. Create and update: Vue.js creates a VirtualDOM tree based on component definitions, and updates VirtualDOM first when the state changes. 2. Differences and patching: Comparison of old and new VirtualDOMs through diff operations, and apply only the minimum changes to the real DOM. 3. Efficiency: VirtualDOM allows batch updates, reduces direct DOM operations, and optimizes the rendering process. VirtualDOM is a strategic tool for Vue.js to optimize UI updates.

Vue.js and React each have their own advantages in scalability and maintainability. 1) Vue.js is easy to use and is suitable for small projects. The Composition API improves the maintainability of large projects. 2) React is suitable for large and complex projects, with Hooks and virtual DOM improving performance and maintainability, but the learning curve is steeper.

The future trends and forecasts of Vue.js and React are: 1) Vue.js will be widely used in enterprise-level applications and have made breakthroughs in server-side rendering and static site generation; 2) React will innovate in server components and data acquisition, and further optimize the concurrency model.

Netflix's front-end technology stack is mainly based on React and Redux. 1.React is used to build high-performance single-page applications, and improves code reusability and maintenance through component development. 2. Redux is used for state management to ensure that state changes are predictable and traceable. 3. The toolchain includes Webpack, Babel, Jest and Enzyme to ensure code quality and performance. 4. Performance optimization is achieved through code segmentation, lazy loading and server-side rendering to improve user experience.

Vue.js is a progressive framework suitable for building highly interactive user interfaces. Its core functions include responsive systems, component development and routing management. 1) The responsive system realizes data monitoring through Object.defineProperty or Proxy, and automatically updates the interface. 2) Component development allows the interface to be split into reusable modules. 3) VueRouter supports single-page applications to improve user experience.

The main disadvantages of Vue.js include: 1. The ecosystem is relatively new, and third-party libraries and tools are not as rich as other frameworks; 2. The learning curve becomes steep in complex functions; 3. Community support and resources are not as extensive as React and Angular; 4. Performance problems may be encountered in large applications; 5. Version upgrades and compatibility challenges are greater.

Netflix uses React as its front-end framework. 1.React's component development and virtual DOM mechanism improve performance and development efficiency. 2. Use Webpack and Babel to optimize code construction and deployment. 3. Use code segmentation, server-side rendering and caching strategies for performance optimization.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Chinese version
Chinese version, very easy to use

WebStorm Mac version
Useful JavaScript development tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver Mac version
Visual web development tools
