第三章、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