Vue实例之render构建+调用
前言
前几篇文章分析了Vue初始化以及Vue实例创建时data、computed、$mount相关的处理,引出了Vue响应式原理的实现以及computed与data不同的处理。
本篇文章是想要探寻下Vue中是如何处理html到vnode以及vnode转换为html的过程,之后会结合Moon.js中关于此过程的处理,比较二者的区别。
而这篇文章的初衷是想要结合此处的实现逻辑,自实现下简易的MVVM框架,目前对于data以及computed响应式原理部分已经完成,之后会添加methods以及html->vnode相互转换部分,而此篇则是起点,之后会有多篇相关文章。
具体分析
首先看看Vue初始化以及new Vue实例创建过程中涉及到的render的处理,如下图:
从上图中可以看出初始化过程中针对render的处理,接下来就深入到每一步中看看其具体的出路逻辑。
初始化时renderMixin
这部分是加载Vue.js文件过程中的处理,涉及到render的是renderMixin函数,实际上该函数主要定义Vue原型方法:
Vue.prototype.$nextTick方法定义
Vue.prototype._render方法定义
主要关注的_render,这里暂不深入,之后会涉及到该处。
new Vue时initRender
创建Vue实例时会调用initRender进行初始化,实际上就是相关属性的定义,主要的属性有:
- _vonde
- $slots
- $scopedSlots
- _c、$createElement:属性值都相同,即h函数,创建vnode对象,非常重要
- $attrs:调用defineReactive实现响应式
- $listeners:调用defineReactive实现响应式
$mount挂载render处理
在$mount中处理render是整个的核心,其中涉及到render相关的处理逻辑如下:
从上图中可以看出compileToFunctions存在相关render的构建过程,顾名思义compileToFunctions:编译成函数,即处理template成render函数。
compileToFunctions具体处理
分析源码梳理了主要的处理逻辑,如下图:
从上图主要逻辑以及具体代码分析可知:
compileToFunctions函数主要处理的三个点如下:
1. 缓存render + key,其中key就是template,即挂载点在内的outHTML
2. 调用compile编译template
3. 调用createFunction构建render函数
而构建出render函数的核心就是compile和createFunction函数了。
这部分我会在下篇文章中具体分析其处理逻辑,这部分也是html转换为具体函数的核心之一
从$mount中compileToFunctions中处理,构建出了render函数,那再来看看render函数的调用。
mountComponent中render相关逻辑
实际上render函数的调用是在mountComponent函数中触发的,梳理逻辑处理如下:
上图是mountComponent主要的处理逻辑,实际上render函数的执行是在_render中处理的。_render函数的结果作为vm._update函数的参数。
这里有一个非常需要注意的点,实际上是在构建Watcher实例触发的:
var updateComponent = function() {
vm._update(vm._render());
};
new Watcher(vm, updateComponent, noop);
实际上在之前data以及computed文章中对于Watcher构造函数实际上就做过说明:
updateComponent会作为getter函数,并且会在Watcher.prototype.get中被调用,而这个步骤就是重新生成html的过程
_render方法
实际上_render中主要的处理也就是render函数的调用,核心代码如下:
var vnode = render.call(vm._renderProxy, vm.$createElement);
return vnode;
总结
本篇文章主要梳理分析了render的创建以及调用的过程,其中涉及到3个主要入口函数:
- renderMixin用于定义_render函数
- initRender用于定义相关属性,例如$createElement等
- $mount是核心处理的入口函数
构建render函数
$mount -> compileToFunctions函数生成render函数
render函数调用
生成render函数 -> mountComponent -> new Watcher -> Vue.prototype._render调用
实际上通过上面这两个步骤,也得到了html -> vnode 以及vnode -> html两个过程的具体处理,其对应的函数分别是:
html -> vnode处理函数:compileToFunctions和Vue.prototype._render
vnode -> html处理函数:Vue.prototype._update
下篇文章就具体分析html -> vnode的过程。