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!

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

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











PHP and Vue: a perfect pairing of front-end development tools. In today's era of rapid development of the Internet, front-end development has become increasingly important. As users have higher and higher requirements for the experience of websites and applications, front-end developers need to use more efficient and flexible tools to create responsive and interactive interfaces. As two important technologies in the field of front-end development, PHP and Vue.js can be regarded as perfect tools when paired together. This article will explore the combination of PHP and Vue, as well as detailed code examples to help readers better understand and apply these two

Django is a web application framework written in Python that emphasizes rapid development and clean methods. Although Django is a web framework, to answer the question whether Django is a front-end or a back-end, you need to have a deep understanding of the concepts of front-end and back-end. The front end refers to the interface that users directly interact with, and the back end refers to server-side programs. They interact with data through the HTTP protocol. When the front-end and back-end are separated, the front-end and back-end programs can be developed independently to implement business logic and interactive effects respectively, and data exchange.

As a fast and efficient programming language, Go language is widely popular in the field of back-end development. However, few people associate Go language with front-end development. In fact, using Go language for front-end development can not only improve efficiency, but also bring new horizons to developers. This article will explore the possibility of using the Go language for front-end development and provide specific code examples to help readers better understand this area. In traditional front-end development, JavaScript, HTML, and CSS are often used to build user interfaces

As a C# developer, our development work usually includes front-end and back-end development. As technology develops and the complexity of projects increases, the collaborative development of front-end and back-end has become more and more important and complex. This article will share some front-end and back-end collaborative development techniques to help C# developers complete development work more efficiently. After determining the interface specifications, collaborative development of the front-end and back-end is inseparable from the interaction of API interfaces. To ensure the smooth progress of front-end and back-end collaborative development, the most important thing is to define good interface specifications. Interface specification involves the name of the interface

Methods for implementing instant messaging include WebSocket, Long Polling, Server-Sent Events, WebRTC, etc. Detailed introduction: 1. WebSocket, which can establish a persistent connection between the client and the server to achieve real-time two-way communication. The front end can use the WebSocket API to create a WebSocket connection and achieve instant messaging by sending and receiving messages; 2. Long Polling, a technology that simulates real-time communication, etc.

Django: A magical framework that can handle both front-end and back-end development! Django is an efficient and scalable web application framework. It is able to support multiple web development models, including MVC and MTV, and can easily develop high-quality web applications. Django not only supports back-end development, but can also quickly build front-end interfaces and achieve flexible view display through template language. Django combines front-end development and back-end development into a seamless integration, so developers don’t have to specialize in learning

In front-end development interviews, common questions cover a wide range of topics, including HTML/CSS basics, JavaScript basics, frameworks and libraries, project experience, algorithms and data structures, performance optimization, cross-domain requests, front-end engineering, design patterns, and new technologies and trends. . Interviewer questions are designed to assess the candidate's technical skills, project experience, and understanding of industry trends. Therefore, candidates should be fully prepared in these areas to demonstrate their abilities and expertise.

Vue.js is suitable for small and medium-sized projects and fast iterations, while React is suitable for large and complex applications. 1) Vue.js is easy to use and is suitable for situations where the team is insufficient or the project scale is small. 2) React has a richer ecosystem and is suitable for projects with high performance and complex functional needs.
