
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渲染成真实节点