第三章、Vue.js3的设计思路
简易的渲染器
function renderer(vnode, container) {
if (typeof vnode.tag === 'string') {
mountElement(vnode, container)
} else if (typeof vnode.tag === 'object') {
mountComponent(vnode, container)
}
}
// 渲染组件
function mountComponent(vnode, container) {
// 组件本质是虚拟dom的封装,可以是一个返回虚拟dom的函数,也可以是一个对象
const subtree = vnode.tag.render()
renderer(subtree, container)
}
// 渲染dom
function mountElement(vnode, container) {
// 创建dom
const el = document.createElement(vnode.tag)
// 遍历vnode.props属性,并将属性添加到dom上
for (const key in vnode.props) {
// on开头的属性为事件
if(/^on/.test(key)) {
el.addEventListener(key.substr(2)/.toLowerCase(), vnode.props[key])
}
}
// 处理children字节点
if(typeof vnode.children === 'string') {
// 字符串表示字节点是文本
el.appendChild(document.createTextNode(vnode.children))
} else if (Array.isArray(vnode.children)) {
// 数组表示有多个字节点 递归渲染
vnode.children.forEach(child => renderer(child, el))
}
// 挂载节点
container.appendChild(el)
}
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
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