概述
正常情况下,使用 js 渲染简单的文本步骤为:

在 Vue 中有一个虚拟 DOM 的概念,Vue 首先会将需要渲染的内容先使用 JS 生成一个虚拟的 DOM 结构,然后再将虚拟 DOM 渲染为真实的 DOM 。
那这会有两个问题:
- 什么是虚拟 DOM?
- 为什么需要引入虚拟 DOM ?
- 虚拟 DOM 是怎么渲染为真实 DOM ?
实现代码 github 地址, 入口文件为 main.js, 源码放在 src目录中,实现一共 110 行代码
DEMO展示
代码:
import Vue from './src/vue'
new Vue({
el: '#app',
data() {
return { message: '简单文本渲染' }
},
render(h) {
return h('div', null, this.message)
}
})
效果:

- 初始化一个Vue实例
- 引用 data 中属性 message
- 渲染文本
过程解析

- VNode也就是对真实Dom节点的一种表示方式,VDom也就是一系列的VNode
- 渲染阶段,会递归遍历 VNode,根据VNode的类型结合 DOM Api 进行Dom操作
核心代码
- Vue的构造函数:
class Vue { constructor(options) { this.$options = options this.initData() this.mount() } initData(){} mount() {} } - 属性代理, 将data中的定义的属性代理到Vue的实例上面去,中间会有一个 data ->
vm._data过程,通过 vm.xxx 获取时,会读取vm._data[xxx]的值:initData() { let data = this.$options.data data = this._data = typeof data === 'function' ? data.call(this, this) : (data || {}) const keys = Object.keys(data) for (let key of keys) { if (!isReserved(key)) { proxy(this, '_data', key) } } } function proxy(target, sourceKey, key) { const definition = { enumerable: true, configurable: true, get: function () { return this[sourceKey][key] }, set: function (val) { this[sourceKey][key] = val } } Object.defineProperty(target, key, definition); } - 生成VNode的过程,也就是使用一个 JS 的 Object 来描述一个DOM节点,其中包含一些属性以及数据:
class VNode { constructor(tag, data, children, text, elm, context) { this.tag = tag this.data = data this.children = children this.text = text this.elm = elm } } - 由VNode转化为真实DOM过程, 也就是patch的过程,首次渲染需要是需要删除
#app元素 (也就是初始化传入的el):function patch($el, vnode) { // 创建元素 createElm(vnode, document.parentNode($el), document.nextSibling($el)) // 删除 #app removeElm(document.parentNode($el), $el) }
总结
文本渲染,通常我们的做法是:直接通过DOM提供的API进行操作。 而Vue中加了一个先生成VNode的过程,然后再借助 DOM 原生的API进行操作。