Vue diff patch 实现
cooljser 2022-01-11 vue
vue 虚拟 DOM 主要做了这三件事:
- 用 js 对象模拟 DOM 树;
- 比较两棵虚拟 DOM 树的差异;
- patch 算法,将虚拟 DOM 转换为真实 DOM。
// @ts-ignore
// @ts-nocheck
// 初始化 patch
function createElement(vnode) {
let tag = vnode.tag; // 目标元素
let attrs = vnode.attrs || {}; // 属性
let children = vnode.children || []; // 子节点
if (!tag) {
return null;
}
// 1. 创建对象的 DOM
let elem = document.createElement(tag);
// 2. 添加属性
for (const attrName in attrs) {
if (Object.hasOwnProperty(attrName)) {
elem.setAttribute(attrName, attrs[attrName]);
}
}
// 3. 将子元素添加到目标元素
children.forEach((childElement) => {
elem.appendChild(createElement(childElement));
});
return elem;
}
// 更新阶段的 patch
function udpate(vnode, newVnode) {
const children = vnode.children || [];
const newChildren = newVnode.children || [];
children.forEach((childElement, index) => {
const newChildElement = newChildren[index];
if (childElement.tag === newChildElement.tag) {
// 递归更新
update(childElement, newChildElement);
} else {
replace(childElement, newChildElement);
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46