vue挂载流程和模板编译
vue挂载流程和模板编译
基于源码构建的两种版本
先了解一下vue
基于源码构建的两个版本,一个是runtime only
(一个只包含运行时的版本),另一个是runtime + compiler
(一个同时包含编译器和运行时的版本)。而两个版本的区别仅在于后者包含了一个编译器。
那么什么叫做编译器:编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序
Runtime + Compiler
一个完整的Vue
版本是包含编译器的,我们可以使用template
进行模板编写。编译器会自动将模板字符串编译成渲染函数的代码,源码中就是render
函数。 如果需要在客户端编译模板 (比如传入一个字符串给 template
选项,或挂载到一个元素上并以其 DOM
内部的 HTML 作为模板),就需要一个包含编译器的版本
Runtime Only
只包含运行时的代码拥有创建Vue
实例、渲染并处理Virtual DOM
等功能,基本上就是除去编译器外的完整代码。Runtime Only
的适用场景有两种: 1.我们在选项中通过手写render
函数去定义渲染过程,这个时候并不需要包含编译器的版本便可完整执行
实例挂载
大致流程:
- 确认挂载节点
- 编译模板为
render
函数 - 渲染函数转换
Virtual DOM
- 创建真实节点
详细流程:
- 确定挂载的
DOM
元素,这个DOM
需要保证不能为html,body
这类根节点。 - 渲染有两种方式,一种是通过
template
模板字符串,另一种是手写render
函数,template模板需要运行时进行编译,而后一个可以直接用render
选项作为渲染函数。因此挂载阶段会有两条分支,template
模板会先经过模板的解析,最终编译成render
渲染函数参与实例挂载,而手写render
函数可以绕过编译阶段,直接调用挂载的$mount
方法。 - 针对
template
而言,它会利用Vue
内部的编译器进行模板的编译,字符串模板会转换为抽象的语法树,即AST
树,并最终转化为一个类似function(){with(){}}
的渲染函数。 - 无论是
template
模板还是手写render
函数,最终都将进入mountComponent
过程,这个阶段会实例化一个渲染watcher
,渲染watcher
的回调函数有两个执行时机,一个是在初始化时执行,另一个是当vm
实例检测到数据发生变化时会再次执行回调函数。 - 回调函数是执行
updateComponent
的过程,这个方法有两个阶段,一个是vm._render
,另一个是vm._update
。vm._render
会执行前面生成的render
渲染函数,并生成一个Virtual Dom tree
,而vm._update
会将这个Virtual Dom tree
转化为真实的DOM
节点。
template模块书写方式
编译流程图
小结
当我们传入选项进行实例化时,最终的目的是将选项渲染成页面真实的可视节点。这个选项有两种形式,一个是以template
模板字符串传入,另一个是手写render
函数形式传入,不论哪种,最终会以render
函数的形式参与挂载,render
是一个用函数封装好的with
语句。渲染真实节点前需要将render
函数解析成虚拟DOM
,虚拟DOM
是js
和真实DOM
之间的桥梁。最终的_update
过程让将虚拟DOM
渲染成真实节点