Reference answer:
When the component is created and updated , Vue will execute the internal update function . This function uses the virtual dom tree generated by the render function to compare the old and new trees, find the difference, and finally update to the real dom. The process of comparing the difference is called diff. Vue completes this process internally through a function called patch . When comparing, Vue uses depth-first and same-level comparison for comparison. When judging whether two nodes are the same, Vue judges through the key and tag of the virtual node . Specifically, first compare the root node , and if they are the same, hang the reference of the real DOM associated with the old node to the new node , and then update the attribute to the real dom as needed, and then compare its child node arrays; if they are not the same, recursively create all real doms according to the information of the new node, and hang them on the corresponding virtual nodes at the same time, and then remove the old dom. When comparing its sub-node arrays, vue uses two pointers for each sub-node array , pointing to the head and tail respectively, and then keeps moving closer to the middle for comparison. The purpose of this is to reuse the real dom as much as possible and destroy and save as little as possible. Create real dom. If they are found to be the same, enter the same comparison process as the root node, and if they are found to be different, move the real dom to a suitable position. This keeps recursive
The traversal continues until the entire tree is compared.
1. Timing of diff
When a component is created, or when a dependent property or data changes, a function is run that does two things:
- Run
_render
to generate a new virtual dom tree (vnode tree) - Run
_update
, pass in the root node of the virtual dom tree, compare the old and new trees, and finally complete the update of the real dom
The core code is as follows:
// vue构造函数
function Vue(){
// ... 其他代码
var updateComponent = () => {
this._update(this._render())
}
new Watcher(updateComponent)
// ... 其他代码
}
diff
happens while _update
the function is running
2. What does the _update function do
_update
The function receives a vnode
parameter, which is the newly generated virtual dom tree
At the same time, the function gets the old virtual dom tree _update
through the properties of the current component_vnode
_update
The function first _vnode
reassigns the properties of the component to point to the new tree
function update (vnode) {
// vnode 新
// this._vnode 旧
let oldVnode = this._vnode;
this._vnode = vnode;
// 对比的目的:更新真实dom
if (!oldVnode) {
this.__patch__(this.$el.vnode);
}
}
Then it will judge whether the old tree exists:
- Does not exist: It means that this is the first time to load the component, so through the internal
patch
function , directly traverse the new tree, generate a real DOM for each node, and mount it onelm
the property of each node
-
Existence: It means that the component has been rendered before, so through the internal
patch
function, compare the old and new trees to achieve the following two goals: -
Complete the minimization of all real DOM
-
Let the nodes of the new tree correspond to the appropriate real dom
3. Comparison process of patch function
Explanation of terms :
- " Same ": refers to the label type and
key
value of the two virtual nodes are the same, butinput
the element depends ontype
the attribute - " New element ": refers to creating a real dom element based on the information provided by a virtual node, and at the same time mount it on the
elm
attribute of the virtual node - " Destruction Element " means:
vnode.elm.remove()
- " Update ": refers to the comparative update of two virtual nodes, which only occurs when the two virtual nodes are "same". The specific process will be described later.
- " Comparing child nodes ": refers to comparing the child nodes of two virtual nodes, the specific process will be described later
Detailed process:
- root node comparison
patch
The function first compares the root node
If two nodes:
- "Same", enter ** "Update" process**
-
Assign the real dom of the old node to the new node:
newVnode.elm = oldVnode.elm
-
Compare the properties of the new node and the old node, and update the changed ones to the real dom
-
The current two nodes are processed, start ** "Comparing child nodes"**
- Are not the same"
-
New node recursive "new element"
-
Old node "Destroy Element"
-
"Compare Child Nodes"
When "comparing child nodes", the starting point of all vue is to:
- try not to do anything
- If not, try to only change the element attribute
- If not, try to move elements instead of deleting and creating elements
- If not, delete and create elements
This article is reproduced from: