Vue初始化流程

288 阅读2分钟

本文章主要针对的是2.0版本的初始化流程,会结合源码和绘图的方式,加深自己对vue原理的掌握。

new Vue 发生了什么

我们知道,new 关键字在Javascript中代表实例化是一个类,而Vue实际上是一个类,让我们来看一下内部的实现:

代码位置: src/core/instance/index.js

先贴流程图: 

可以看到,Vue 的构造函数还是通过ES5的方式来实现的,这样做的好处是方便扩展,通过调用不同的mixin方法,在**Vue.prototype**上添加各类原型方法。

initMixin 方法为Vue添加了 _init 方法,在new Vue的时候会执行该方法,稍后重点分析。

stateMinxin 方法为Vue添加了 $set $delete **$watch**等api。

eventsMinxin 方法为Vue添加了 $emit **$on$off$once**等和事件相关的api。

lifecycleMinxin 方法为Vue添加了**_update (实际会执行patch方法,虚拟dom渲染成真实dom),另外还有$destroy$forceUpdate(强制组件渲染)mountComponent(组件挂载)**

renderMixin 方法为Vue添加了**$nexttick_render(把template编译成render function,最后生成Vnode**)。

好处: 通过把不同的功能逻辑拆成一些单独的函数执行,让主线程逻辑一目了然,代码逻辑十分清晰。

探索_init方法

代码位置: src/core/instance/init.js

先贴流程图: 

以上是_init内部的函数执行流程,主要干了以下几件事:

1. 定义组件实例 

2. 初始化生命周期 

3.初始化事件中心 

4. 初始化渲染 

5.初始化state(响应式核心)

6.判断用户有没有传el选项,有el开始执行$mount挂载流程

探索挂载逻辑

由于vue提供了不同的版本,一个是Runtime版本,一个是Runtime+compiler版本。两者区别如下:

  • Runtime Only版本

通过借助webpack的vue-loader把.vue文件编译成可执行的 Javascript 函数,在编译阶段就执行。所以这个版本只包含运行时的Vue代码,更轻量,体积更小。

  • Runtime + Compiler版本

不会对代码进行预编译,如果在配置项中写了 template 选项 ,内部在运行时进行代码编译,把template编译成**render**函数,该版本包含编译代码,包体积更大,推荐使用Runtime only版本。

new Vue({ // 需要编译
  template: '<div>{{ hi }}</div>'
})

new Vue({ // 不需要编译
  render (h) {
    return h('div', this.hi)
  }
})

基于上面提到的两个不同版本,我们找到了**$mount**的入口,代码位置: src/platforms/web/entry-runtime-with-compiler.js

先贴流程图:

开始挂载: mountComponent 

代码位置: src/core/instance/lifecycle.js

先贴流程图: 

核心逻辑其实还是在**watcher内部,watcher**作为响应式的核心是非常重要的。updateComponent在组件初始化和更新的时候都会被执行,_render和_update依次被执行,后面我们会重点分析_render和_update内部具体做了哪些工作。

最后拿**vue**官网的生命周期图来和上述的分析流程做一个对比,加深自己对vue生命周期的理解和掌握:

更新逻辑和销毁逻辑后续再补充,祝大家学习愉快,吃透vue原理。