《Vue.js设计与实现》读书笔记(2)

95 阅读2分钟

第三章 Vue.js的设计思路

使用JavaScript对象来描述UI的方式,其实就是所谓的虚拟DOM。vue.js3除了支持使用模板描述UI外,还支持虚拟DOM描述UI。其实我们在vue.js组件中手写的渲染函数就是使用虚拟DOM来描述UI的。
什么是组件的渲染函数?
一个组件要渲染的内容是通过渲染函数来描述的,也就是render函数,vue.js会根据组件的render函数的返回值拿到虚拟DOM,然后就可以把组件的内容渲染出来了。
渲染器的作用就是把虚拟DOM渲染成真实DOM。
假设我们有如下虚拟DOM:

const vnode = {
    tag: 'div',
    props: {
        onclick: ()=> alert('hello')
    },
    children: 'click me'
}

那么,我们怎么编写一个渲染器,把上面这段虚拟DOM渲染为真实DOM:

function renderer(vnode, container){
    // 使用vnode.tag作为标签名称创建DOM元素
    const el = document.createElement(vnode.tag)
    // 遍历vnode.props,将属性、事件添加到DOM元素
    for(const key in vonde.props){
        if(/^on/.test(key)){
        // 如果key以on开头,说明它是事件
            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)){
        // 递归调用render函数渲染子节点,使用当前元素el作为挂载点
        vnode.children.forEach(child => renderer(child, el))
    }
     
    // 将元素添加到挂载点下
    container.appendChild(el)
}

由此可知,渲染器renderer的实现思路,总体来说分为三步:

  1. 创建元素
  2. 为元素添加属性和事件
  3. 处理children

其实虚拟DOM除了能够描述真实DOM之外,还能够描述组件。
组件的本质就是一组DOM元素的封装,这组DOM元素就是组件要渲染的内容。

编译器的作用就是将模板编译为渲染函数。
对于编译器来说,模板就是一个普通的字符串,它会分析该字符串并生成一个功能与之相同的渲染函数。
所以无论是使用模板还是直接手写渲染函数,对于一个组件来说,它要渲染的内容最终都是通过渲染函数产生的,然后渲染器再将渲染函数返回的虚拟DOM渲染为真实DOM,这就是模板的工作原理,也是vue.js渲染页面的过程。
编译器和渲染器之间是存在信息交流的,而它们之间交流的媒介就是虚拟DOM对象。
组件的实现依赖于渲染器,模板的编译依赖于编译器,它们都是Vue.js的核心组成部分,它们共同构成一个有机整体,不同模块之间互相配合,进一步提升框架性能。