Vue.js 源码阅读 之 新建Vue实例

从Vue官网的教程进而开始阅读Vue2.0的源码。Vue源码高度解耦,十分优雅,阅读的时候,也能更加深入了解作者如何设计MVVM框架,巩固自己JavaScript的知识。
本文将一步步引导读者,新建一个Vue实例的背后到底发生了什么,源码是如何实现的?
本文不深追Vue各种细节代码,优先找到新建Vue实例的主线过程。

以一个简单的Vue实例来介绍整个的实例的构造过程

var app = new Vue({
el:'#app',
data:{
message:'Hello Vue'
}
})

从官网教程可以获得如下new Vue()的生命周期。
Vue的生命周期
从Vue的GitHub的下载最新的Vue项目,里面的src目录就是Vue的源码.
Ok,现在进入Vue的源码阅读。

入口文件

Vue的src目录中包含entries(入口)文件夹,里面包含各种入口文件。

运行如下代码:

npm run dev

可以看到

rullup....... TARGET:web-full-dev

打开build/config.js可以看到builds变量中web-full-dev所指向的入口文件即web-runtime-with-compiler.js
打开web-runtime-with-compiler.js,可以看到如下代码:

import Vue from 'core/index'

要查找Vue的构建函数就必须要src/core目录逐层下去找。

构造函数

寻找构建函数,直到文件:src/core/instance/index.js

function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}

Vue函数设定是构造函数而非普通函数。构造函数在通过new创建的过程,this绑定到实例。构造函数也通过this instanceof Vue来判断是否通过new来创建的.
然后执行_init()方法。
至于该文件下面的代码如:

initMixin(Vue) //初始化入口,各种初始化工作
stateMixin(Vue) //数据的绑定
eventsMixin(Vue) //事件的方法
lifecycleMixin(Vue) //生命周期的方法
renderMixin(Vue) //渲染的方法

是用来分别增加Vue构造函数的原型方法。
this._init(options)就是存在initMixin里面。

初始化

打开文件:src/core/instance/init.js
除了一开始合并options属性的代码,可以看到初始的工作.代码如下:

// expose real self
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false)
mark(endTag)
measure(`${vm._name} init`, startTag, endTag)
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}

以上代码分别对应Vue生命周期图中从new Vue()到$mount之间的过程。