"Vue Source Code Interpretation" explains Vue's Diff algorithm in simple terms (1)

Happy New Year everyone~ The new year is about to begin again, keep working hard...
~
Please pay attention, ask for collection, ask for likes, if you find that the blogger has written something unreasonable, please let me know in time, thank you~

foreword

insert image description here

Recently, I was looking at the source code of Vue2.6.14 version. This series of blog posts mainly records the experience related to personal source code learning. I hope my personal learning experience can help you a little bit while you are learning;This article mainly records the learning about the Diff algorithm, and understands the general operation logic of the Diff algorithm and the ins and outs of the Virtual-DOM;Note that this article does not involve the source code of the Diff algorithm. The analysis of the source code will be carefully decomposed in the next blog post

Read it patiently, you will definitely gain something;

Virtual-dom

Before starting to learn about the Diff algorithm, you must first understand why there is a Diff algorithm and what the Diff algorithm exists to solve
.

MVC和MVVM

In today's front-end field, the MVVM model is very popular, making the original MVC development model almost extinct, and the most famous frameworks in the MVVM development model are: React, Vue, Angular. A friend of mine asked me before:What is the advantage of the MVVM model compared to MVC? Searching on the Internet is explaining what is MVVM and what is MVC, but I can't see why

In the front-end field, the meaning of MVC is almost as follows: M (Model) data, V (View) representing the view, C (Controller) business logic , a bit like this

insert image description here
For example, the JQuery example in MVC:

  • M stands for data (which can be requested later or entered by the user);
  • V is the page corresponding to HTML, including the operation logic of the DOM, etc.;
  • C is the business logic and interaction logic, such as how to process and fill the data on the page after the user has entered the data, and vice versa;

In this mode, C, that is, the Controller layer, is actually very weak and its functions are not strong.The View layer is very thick anyway, all operations on DOM processing are in this layer. Once the data changes, it is necessary to re-operate the DOM. In the words of the design pattern, it isvery high coupling, If there is a change in the business, the code will often be rewritten, and it is not well written... So there is also the MVVM model, then what is the biggest difference between the two models?

Before answering this question, let me ask a question. After the DOM renders the page, what operations will have a greater impact on the performance of the browser?In my opinion, repaint and reflow in the GUI rendering thread can have a big impact on browser performance, there may be some friends who don't know what is redrawing and what is reflow. Let's briefly talk about it here.

  • Redraw: When some elements need to update their properties, and the update of these properties only affects the appearance and style of the element, but not the layout, such as background-color. It's called repainting .
  • Reflow: When the page layout changes, for example, we modify the width and height of an element, the DOM tree structure will also change, and the DOM tree and the rendering tree are closely connected. After the DOM tree is constructed, the rendering tree will also follow The process of re-rendering the page is called reflow .

After understanding redrawing and reflow, then we can talk about why there is a pattern of MVVM,Let me start with my personal conclusion. I think there is not much difference between MVC and MVVM in essence., MVVM is a development mode born out of MVC. In the traditional MVC design mode, almost all operations on the DOM are manual , that is, developers need to manually develop the relevant control code. For example, we need to obtain the DOM first to update the data. Then overwrite the value in the DOM,This also causes developers to frequently manipulate the DOM, the page will be frequently redrawn and reflowed. The MVVM mode optimizes this step. It completely enlarges the functions of the Controller, and in principle, there is no direct relationship between the data and the page DOM, and it is all handed over to the Controller.Including operations on the DOM are also automatically rendered by the framework, the following example
:insert image description here

The advantage of this change is that developers can focus on data and business processing. The C layer has undergone an evolution, and all DOM operations are summarized into the VM (ViewModel). The essence of the VM will also operate the DOM, but The framework has the best group of developers who write algorithms to calculate how to optimally process DOM dynamically, and what kind of operation DOM consumes the least performance and has the best experience, thenHow is the optimization done in the VM, then we have to talk about the protagonist of this section, Virtual-dom

Virtual-dom

Virtual-dom, also known as virtual DOM, is essentially using JS objects to describe the DOM structure. Why do you do this, because operating the DOM will redraw and reflow, which will increase browser pressure, but operating the DOM is very simple. a simple example

// html代码
<div><a href="oliver.blog.csdn.net"></a></div>

After changing to virtual DOM, it is almost similar to this

{
    
    
  tagName:"div",
  children:[
    {
    
    
      tagName:"a",
      href:"oliver.blog.csdn.net"
    }
  ]
}

Every time you want to render a page, you only need to render it according to the virtual DOM tree. Therefore, after each data change in MVVM, the attributes on the corresponding virtual DOM tree node will also change, and finally unified according to this tree. Render the page, so that the performance can be greatly improved. There may be some friends who still don’t understand how to improve the performance after using the virtual DOM. Let’s take a practical example: ​For
example one operation , we need to update 20 DOM nodes,
After the browser receives the first DOM update request, it does not know that there are 19 more update operations, so the browser will immediately execute the process, and finally execute 20 times.. For example, the first calculation is completed, followed by the next DOM update request, and the value of this node changes in the second DOM update, which also leads to the waste of the first calculation result. Even if the computer hardware has been iteratively updated, the cost of operating the DOM is still expensive, and frequent operations will still cause page freezes, affecting the user experience; ​After
using the

In one operation, there are 20 actions to update the DOM. The virtual DOM will not operate the DOM immediately, but save the diff content of the 20 updates to a local object, and finally update the JS object to the DOM tree at one time., and then perform subsequent operations to avoid a large amount of unnecessary computation. Therefore, the benefits of virtual DOM nodes are obvious. The update of the page can be fully reflected on the JS object (virtual DOM), and the speed of operating the JS object in the memory is obviously faster. After the update is completed, the final JS object Map it to the real DOM and let the browser draw it.
​(Note: It is emphasized here that it is an operation)

At this point, I believe that my friends should be able to understand what Virtual-dom is and its advantages.The algorithm of how to compare new nodes and old nodes in Virtual-dom is our protagonist Diff algorithm;

Other advantages

In fact, the advantages of Virtual-dom are far more than the improvement in performance. Even because of its existence, the cross-end of JavaScript has been improved again, because through the virtual DOM, we can fully identify the composition and style of page elements.
insert image description here

By converting traditional HTML, CSS, and JavaScript into Virtual-dom, Virtual-dom is like a standard and regularizedStandard data, this kind of data describes all the element attributes on the entire page, and then de-translates it on the corresponding end to achieve the purpose of cross-end;

summary

In the development mode of MVVM, the concept of Virtual-dom is introduced. It describes the entire DOM tree with JS objects. Before updating the DOM, it is first processed by Virtual-dom, and finally updated to the DOM at one time. Improve browser performance, this Diff algorithm is the algorithm for comparing new and old nodes in Virtual-dom;

Diff algorithm

Introduction

Finally introduced the Diff algorithm. As we mentioned above, the Diff algorithm is actually used in Virtual-dom.A new abstraction layer is added to the MVVM development mode to simulate the DOM structure, and the Diff algorithm is used to compare and calculate, to compare which nodes in the new and old Virtual-dom have changed, and only update these DOM nodes that have changed
;

Diff's strategy

Compare by level diff

Let’s talk about the comparison strategy of the Diff algorithm in the MVVM framework. After all, the comparison between the old and the new Virtual-dom is not a blind comparison, see a picture
insert image description here

In Vue or React, the same-level comparison strategy is followed, that is to say, the first layer of blue in the old Virtual-dom is only compared with the first layer of the new Virtual-dom, and the first layer of the old Virtual-dom is compared. The second layer of purple is only compared with the second layer of the new Virtual-dom. According to statistics, it is found that only a few cases will occur because the entire DOM structure has been updated. In most cases, the level of the DOM will not change;

diff by type

How do you understand this? For example, there are components in Vue or React. If the diff algorithm finds that the types of components are different during the comparison, then the component including its subcomponents will be destroyed and replaced with new components. It will not be time-consuming and laborious to continue to compare whether its sub-components have changed.
insert image description here

For example, the component type of the first layer in this example is a triangle, which refers to two sub-components. After the change, the component type of the first layer becomes a pentagon, but the sub-components have not changed. This is because the diff will not say that because As long as the first layer changes, none of the sub-components have changed, so only the first-layer components are changed, keeping the second triangle, it will destroy the entire blue triangle and all its sub-components, replace the whole with a pentagon , and create a new one There are two subcomponents
;

Perform process analysis

Don't look at the source code yet, let's first understand the execution process of the Diff algorithm. The source code can be put into the next blog post for line-by-line analysis. Let's take a look at the legend first. The legend is the old and new nodes that are supposed to be compared.
insert image description here

Let's talk about the meaning first:The upper row represents the old node, the lower row represents the new node, the virtual-dom represented by the big circle is the virtual DOM, and the small circle represents the real DOM corresponding to the virtual DOM;

When the comparison starts, the Diff algorithm will mark the pointers of oldStartIdx, oldEndIdx, newStartIdx, and newEndIdx to the two node sequences respectively, which are roughly as follows:
insert image description here

In other words, the start and end positions are marked respectively, and the end of the mark is the official start of the comparison logic
;

Step 1: Compare oldStartIdx and newStartIdx

The comparison is to compare whether the oldStartIdx of the old Virtual-dom and the newStartIdx of the new Virtual -dom are the same ** .
insert image description here
If the node is the same, then both oldStartIdx and newStartIdx will move backward one bit, and become as follows**
insert image description here

Continue to compare the second node, that is, node B and node E, this is Diff found that node B and node E are not the same node, then it will compare
endIdx

Step 2: Compare oldEndIdx and newEndIdx

Like startIdx, the comparison will compare whether the oldEndIdx of the old Virtual-dom and the newEndIdx of the new Virtual-dom are the same **, ** is also the comparison as shown below
insert image description here

The comparison result shows that the oldEndIdx of the old Virtual-dom and the newEndIdx of the new Virtual-dom are the same node, then the endIdx will also move forward 1 bit like the startIdx
insert image description here

At this point, it will enter the third loop, and continue to compare whether the oldStartIdx of the old Virtual-dom and the newStartIdx of the new Virtual-dom are the same node. At this time, oldStartIdx and newStartIdx are not the same, then continue to compare the old Virtual- The oldEndIdx of dom and the newEndIdx of the new Virtual-dom are not the same , so a third comparison will be performed at this time, comparing oldSatrtIdx and
newEndIdx

Step 3: Compare oldSatrtIdx and newEndIdx

This step of comparison is to compare oldSatrtIdx and newEndIdx, as shown in
insert image description here
the figure. The comparison result shows that oldSatrtIdx and newEndIdx are the same node, but the position has changed , then diff will transfer and reorder the position of B, and adjust the position as follows
insert image description here
In addition, the positions of oldSatrtIdx and newEndIdx will also be shifted by one bit at the same time as the transfer, as shown below
insert image description here

Then continue with a new round of comparison:

  1. Compare whether oldSatrtIdx and newStartIdx are the same node, if not, continue to compare;
  2. Compare whether oldEndIdx and newEndIdx are the same node, if not, continue to compare;
  3. Compare whether oldStartIdx and newEndIdx are the same node, if not, continue to compare;
  4. At this point, a new comparison method will appear to compare whether oldEndIdx and newStartIdx are the same node

Step 4: Compare oldEndIdx and newStartIdx

This step is to compare whether oldEndIdx and newStartIdx are the same node , and find that they are not. If, if oldEndIdx and newStartIdx are found to be the same node, then Diff will adjust the position of this node and move it to the front of the oldStartIdx node ; In the example shown in the figure, oldEndIdx and newStartIdx are not the same node, so the traversal operation will be performed at this time;

Step 5: Traverse oldStart to oldEndIdx

The changed operation is roughly as follows: Diff will compare all nodes between oldStart to oldEndIdx and newStartIdx nodes one by one to see if they are the same, if they are the same, adjust the position, and the position is in front of oldStart ;

Step 6: Create a new node

This step is an operation that does not have the same node. As shown in the figure, when the comparison is completed, it is found that the E node does not exist in the old Virtual-dom. What should I do? At this time, diff will create a node, and the location of the node is at before the position of oldStartIdx
insert image description here

After completing this step, newEndIdx will move forward one bit, and become like this
insert image description here

At this time, it is found that newEndIdx is already smaller than newStartIdx, which means that the comparison between the old Virtual-dom and the new Virtual-dom has ended
;

Step 7: Clean up old nodes
In this step, all nodes between oldStartIdx and oldEndIdx will be deleted, and the old virtual nodes will be deleted, which becomes like this
insert image description here

In this way, a new result appears and the comparison ends
;

Handling of keys

Some friends may know that there is another thing in Vue that is officially emphasized, that is key, let’s see what the official says
:

​To give Vue a hint so that it can keep track of the identity of each node and thus reuse and reorder existing elements, you need to provide each item with a unique key attribute:

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

It is recommended to provide the key attribute when using v-for whenever possible, unless traversing the output DOM content is very simple, or is deliberately relying on the default behavior for performance gains.

The original text is almost like this, so what is the role of this key in the execution process? continue to look at the picture
insert image description here

Assuming that there is a node E between node C and node D, when we have completed the four-step comparison, we need to traverse . At this time, before traversing, the diff will first go to the node map to query, this Whether the node has existed before, how to say it, that is, Vue will mark each existing node and save it, which is probably like this

var map = {
    
    
	"key-A":0,
  "key-E":3
}

Before traversing, check whether the node exists. If it is found, the position of the node can be directly obtained, and there is no need to traverse oldStartIdx and oldEndIdx. The performance of this step is greatly improved. The node moves to the front of oldStartIdx
insert image description here

Now I understand, if you don't set the Key, then the worst case complexity of the algorithm will be twice the complexity of setting the Key, so it is strongly recommended to set the Key
;

summary

This section mainly describes what is the Diff algorithm, and what is the process of the Diff algorithm, what is the function of the key in Vue, and how big is the optimization after the key is set;

Guess you like

Origin blog.csdn.net/zy21131437/article/details/122814417