render 函数
1.Vue项目的两种模式
在使用 Vue-cli 脚手架构建 Vue 项目时,会遇到一个选项:Vue Build。其中有两个选择,即Runtime + Compiler
和Runtime-only
。
这两种模式分别代表:
Runtime + Compiler
:运行程序 + 编译器Runtime-only
:仅运行程序,相较于上面的模式要轻大约 6KB,但是 template(或者任何特定于Vue的HTML)只允许在 .vue 文件中使用,在其它地方使用需要依靠render
函数。
1.1 两种模式的区别
首先,runtime-only
比runtime-compiler
轻 6kb,代码量更少
其次,runtime-only
运行更快,性能更好
runtime-only
其实只能识别render
函数,不能识别template
,.vue 文件中的template
也是被 vue-template-compiler 翻译成了render
函数,所以只能在 .vue 里写 template
。
1.2 解释
这两种模式生成的项目代码模板的区别主要在 main.js 中,其它文件中基本上是一样的:
可以看到,在runtime-only
模式中,创建 Vue 实例时使用的是render
函数。
而在runtime-compiler
模式中,则是使用了template属性来创建 html 模板。
再来看下面这张图:
其中反映的是 Vue 的运行过程。
对于runtime-compiler
模式来说,它的代码运行流程是:template → ast → render → virtual dom → UI,即:
- 首先将 Vue 中的
template
模板进行解析,将其解析成为 abstract syntax tree 即 ast 抽象语法树。 - 将抽象语法树再编译为
render
函数。 - 将
render
函数翻译为 virtual dom,即虚拟DOM。 - 将虚拟DOM展示在页面中。
而对于runtime-only
模式来说,它的代码运行流程为:render → virtual dom → UI,即省略了从template
到 ast 再到render
函数的过程,因此,它相较runtime-compiler
模式更快,代码量更少。
但需要注意的是,runtime-only
模式中不是没有写template
,只是把template
放在了.vue 的文件中了,并有一个叫 vue-template-compiler 的开发依赖时将 .vue 文件中的template
解析成render
函数。 因为是开发依赖,不在最后生产中,所以最后生产出来的运行的代码没有template
。
2.VNode虚拟节点
2.1 VNode 是什么?
VNode 是 JS 对象,准确来说是 JS 中的一个类,可以生产不同类型的vnode实例,不同类型的实例表示不同类型的真实DOM。
VNode 表示Virtual Dom Node
,即虚拟DOM节点。是 JS 中用来描述真实DOM的对象,其中将DOM的标签、属性以及内容都变成对象的属性。
简单来说,VNode 可以理解成DOM节点描述对象,他描述了应该怎样去创建真实的DOM节点。
2.2 VNode 的作用
VNode 表示一个真实的DOM元素,所有真实的DOM节点都是用 VNode 创建并插入到页面中。
看下面这张图:
这里展示了使用 VNode 创建真实的DOM并渲染到视图的过程。可以得知, VNode 和视图是一一对应的。所以,我们可以把 VNode理解成JavaScript对象版本的DOM元素。
渲染视图的过程是先通过render
将template
模版描述成 VNode,然后在使用 VNode 去生成真实的DOM元素,最后插入到页面渲染视图。
2.3 VNode 的优点
- **兼容性强,不受执行环境的影响。**VNode因为是JS对象,不管Node还是浏览器,都可以统一操作,从而获得了服务端渲染、原生渲染、手写渲染函数等能力。
- **减少操作DOM。**任何页面的变化,都只使用 VNode 进行操作对比,只需要在最后一步挂载更新DOM,不需要频繁操作DOM,从而提高页面性能。
3.render
函数
了解完这两种模式的不同,我们再来探讨一下render
函数的作用与具体原理。
3.1 render
函数的作用
render
函数和template
属性一样,都是用来创建 html 模板。且 Vue 推荐在绝大多数情况下使用模板(即template
属性)来创建 HTML,但是,在某些业务场景中,如果真的使用template
来实现,代码会较为冗长繁琐并且会有大量的重复,这时候就可以使用render
渲染函数,因为它相较于模板更接近于编译器。
3.2 render
函数的原理分析
render
函数即渲染函数,它是一个函数,同时,它的参数createElement也是一个函数。
在常见的项目中render
函数的写法如下:
render: (h) => h(App);
这是ES6中的箭头函数的写法,其中将h作为了createElement的别名。所以这段代码实际上相当于:
render: function (createElement) {
return createElement(App);
}
3.3 createElement
函数
该函数的作用是生成一个 VNode 节点,即虚拟节点。而当render
函数得到这个虚拟节点后,会将其返回给 Vue.js 的mount
函数,并将这个虚拟节点渲染为真实的DOM节点,再将其挂载到根节点上。
createElement函数有以下三个参数:
-
一个 HTML 标签字符串,或一个组件选项对象,或者解析上述任何一种的一个 async 异步函数。接收类型包括:
String | Object | Function
,必需! -
一个包含模板相关属性的数据对象,你可以在
template
中使用这些特性。类型:Object
,该属性是可选。 -
子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:
String | Array
,可选。