Vue中的渲染器
Rio 2023-03-02
Vue
框架
说明
Vue渲染器笔记总结
# 渲染器
渲染器的作用就是把虚拟 DOM 渲染为真实 DOM
// 给定一个虚拟dom
const vnode = {
tag: 'div',
props: {
onclick: () => alert('hello')
},
children: 'click'
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- tag 用来描述标签名称,所以 tag: 'div' 描述的就是一个标签。
- props 是一个对象,用来描述标签的属性、事件等内容。可以看到,我们希望给 div 绑定一个点击事件。
- children 用来描述标签的子节点。意思是 div 标签有一个文本子节点:click me
接下来,我们需要编写一个渲染器,把上面这段虚拟 DOM 渲染 为真实 DOM
- vnode:虚拟 DOM 对象。
- container:一个真实 DOM 元素,作为挂载点,渲染器会把虚 拟 DOM 渲染到该挂载点下。
function renderer(vnode, container) {
if (typeof vnode.tag === 'string') {
// 说明 vnode 描述的是标签元素
mountElement(vnode, container)
} else if (typeof vnode.tag ==="function") {
// 说明 vnode 描述的是组件
mountComponent(vnode, container)
}
}
// 标签元素渲染
function mountElement(vnode, container) {
// 使用vnode.tag作为标签名称创建dom元素
const el = document.createElement(vnode.tag);
// 遍历vode.props将属性事件添加到dom元素
for(const key in vnode.props) {
// 如果 key 以 on 开头,说明它是事件
if(/^on/.test(key)){
el.addEventListener(key.substr(2).toLowerCase(),
vnode.props[key],
)
}
}
// 处理 children
if (typeof vnode.children === 'string') {
// 如果 children 是字符串,说明它是元素的文本子节点
el.appendChild(document.createTextNode(vnode.children))
} else if (Array.isArray(vnode.children)){
// 递归地调用 renderer 函数渲染子节点,使用当前元素 el 作为挂载点
vnode.children.forEach(child => renderer(child, el));
}
// 将元素添加到挂载点下
container.appendChild(el);
}
// 组件渲染
function mountComponent(vnode, container) {
// 调用组件函数,获取组件要渲染的内容(虚拟 DOM)
const subtree = vnode.tag();
// 递归地调用 renderer 渲染 subtree
renderer(subtree, container)
}
renderer(vnode, document.body) // body 作为挂载点
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
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
# 组件与模板
组件其实就是一组虚拟 DOM 元素 的封装,它可以是一个返回虚拟 DOM 的函数,也可以是一个对象,但 这个对象下必须要有一个函数用来产出组件要渲染的虚拟 DOM
const MyComponent = function () {
return {
tag: 'div',
props: {
onClick: () => alert('hello')
},
children: 'click me'
}
}
const vnode = {
tag: MyComponent
}
renderer(vnode, document.body) // body 作为挂载点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
组件的实现依赖于渲染器,模板的编译依赖于编译器,模板会被一个叫作编译器的程序编译为渲染函数
要渲染的内容最终都是通过渲染函数产生的,然后渲染器再把 渲染函数返回的虚拟 DOM 渲染为真实 DOM,这就是模板的工作原 理,也是 Vue.js 渲染页面的流程
渲染器的作用是,把虚拟 DOM 对象渲染为真实 DOM 元素。它的工作原理是,递归地遍历虚 拟 DOM 对象,并调用原生 DOM API 来完成真实 DOM 的创建