new Vue() & JSX(一)

151 阅读1分钟

获取 render() 函数并生成渲染 watcher

上文说到初始化最后执行 $mount() 函数,接下来就重点介绍该 mount 流程,部分代码就暂时不上图了!

$mount() => mountComponent() 流程:

执行 $mount() 函数

1、首先获取 el 节点的 DOM 对象,然后对 el 进行判断,不能挂载在 body/html 上。

2、然后判断 vm.$options 上是否有 render() 函数,若没有则获取 template/el 属性对应的 html 内容的字符串。然后再通过 compileToFunctions() 函数将该字符串转成 render() 函数并赋值 vm.$options.render = render。最后再调用原 $mount() 函数。

提示:在 Vue2.0 以后,所有组件都需要 render 函数渲染,无论是单文件 *.vue,还是 el/template 都会转 render 函数,这是在线编译过程,调用 compileToFunctions 函数实现。

3、最后调用原 $mount() 函数传入两个参数,第一个参数 el 表示挂载的元素,经过转换最后 elDOM 对象,第二个参数与服务器端渲染相关。最后实际调用 mountComponent(this, el) 函数。


执行 mountComponent() 函数

1、首先缓存 vm.$el = el; 然后再次判断属性 vm.$options.render 是否存在,若不存在则进行赋值:vm.$options.render = createEmptyVNode(); 该函数返回一个空的 VNode 对象节点。

2、接着执行钩子函数 callHook("beforeMount")

3、然后实例化渲染 watcher,如下:

image.png

如上图所示,准备一个 updateComponent() 函数,即为渲染 watcher 所持有的 getter() 函数,当页面渲染时触发该函数。

然后实例化渲染 watcher。在实例化渲染 watcher 过程中首先进行 vmwatcher 互相关联。然后在实例化渲染 watcher 的最后会求值 watcher.value

this.value = this.lazy ? undefined : this.get();

// this.get() 函数的简单定义
get() { return this.getter() }

所以在求值 watcher.value 时会执行 this.get() => this.getter() => updateComponent() 函数。其实相当于执行 vm._update(vm._render()),在此方法内先调用 vm._render() 函数生成虚拟 VNode,然后调用 vm._update() 函数更新 DOM

4、最后判断当前实例的父虚拟 VNode 是否存在,即为 vm.$vnode 是否存在,若不存在则为根 Vue 实例 ,然后设置 vm._isMounted = true;,表示已经挂载。最后执行生命周期 callHook("mounted") 钩子函数。