学习中使用的Vue是v2.5.17-beta.0 Runtime+Compiler版本
本节主要讲解Vue构造函数初始化的大概流程
Vue构造函数定义
在我们使用Vue的时候,通常都是
1 | new Vue({ |
那么这个Vue构造函数是从哪里来的呢?
在vue-cli搭建的项目中,我们开始开发的时候都会执行npm run dev
命令,在package.json
文件中可以看到dev
命令实际上执行的是rollup -w -c scripts/config.js --environment TARGET:web-full-dev
找到scripts/config.js
中的web-full-dev
1 | 'web-full-dev': { |
由此得知,入口文件就是web/entry-runtime-with-compiler.js
根据scripts/alias.js
中配置的项目路径别名得知,入口文件完整路径是src/platforms/web/entry-runtime-with-compiler.js
1 | // src/platforms/web/entry-runtime-with-compiler.js |
1 | // src/platforms/web/runtime/index.js |
1 | // src/core/index.js |
1 | // src/core/instance/index.js |
经过了这么多个文件,终于找到了Vue
构造函数定义的地方
为什么找一个构造函数就翻了4个文件才找到?
首先,Vue.js的源码都在src目录下,目录结构如下
1 | src |
我们从入口开始的前两个文件夹是在platforms/web
下的,后来开始引入了src/core
下面的代码。由代码目录结构大概就可以看出,这么做是为了复用核心代码。最终引用到src/core
的代码是通用的Vue
代码,不论哪个平台最终都会引入此处定义的构造函数
platforms
下的代码是根据不同平台和版本不同而编写的,如我们讲解的Runtime+Compiler版本,入口是src/platforms/web/entry-runtime-with-compiler.js
,而它引用Vue来自src/platforms/web/runtime/index.js
,而Runtime+Compiler版本比runtime版本就是多了一个编译器,由此来看,就很简单了。在src/platforms/web/entry-runtime-with-compiler.js
中引入Vue并且主要所做的事,就是给Vue
添加了实例方法$mount
而在runtime版本的入口entry-runtime
中,仅仅是引入了Vue,并没有做其他处理。
从这里可以看出,我们写代码的时候也可以像Vue一样,抽出通用的部分,根据不同的应用再给通用的部分添加各种定制化的功能,这样能实现代码最大程度上的复用。
Vue构造函数
1 | // src/core/instance/index.js |
在Vue
构造函数定义的文件下可以看到,定义了Vue
构造函数,并且提示必须使用new
操作符来调用Vue
;引入并执行了initMixin
、stateMixin
、eventsMixin
、lifecycleMixin
、renderMixin
,由上面注释可以看出,这5个方法在Vue.prototype
上添加了很多方法,这些就是我们平时能在Vue
实例上使用的方法。
之前也说过,我们通过了4个文件才找到Vue构造函数的定义,接下来看看src/core/instance/index.js
这也是通用的Vue定义。
1 | import Vue from './instance/index' |
这个文件中的代码比较简单,主要执行了initGlobalAPI
函数并定义了几个变量initGlobalAPI
通过名字也能看出来,初始化全局API;就是在Vue
构造函数上定义了很多静态方法,调用的时候是直接使用Vue
调用,而不是使用实例调用;同时还在Vue.options上初始化了一些属性
使Vue.options变成
1 | Vue.options = { |
通过此段Vue构造函数的分析,可以看出Vue把各个功能都分开在各个文件里,我们也可以借鉴这样的设计,会让代码看起来十分清晰,通过函数名大概就能知道各个功能的作用,并且非常利于维护。
Vue平台化的包装
前面已经知道core
下的Vue是与平台无关的,在我们使用的时候还有两个platforms
下的文件对Vue
进行了引用
1 | // src/platforms/runtime/index.js |
首先为Vue.config
添加一些属性,Vue.config
初始化是在intGlobal
中,引入了core/config
文件,最开始是
1 | Vue.config = { |
将会覆盖部分默认配置
接着执行
1 | extend(Vue.options.directives, platformDirectives) |
再次修改Vue.options
,最终将Vue.options
变为
1 | Vue.options = { |
之后在Vue.prototype
上添加__patch__
$mount
方法
再往下是开发工具相关的代码,最后导出Vue
接着看最后一个文件,就是我们的入口
1 | /* @flow */ |
上面是省略的代码,这个文件主要做的是:缓存了Vue.prototype.$mount
方法,进行了重写;添加了Vue.complie
全局API。
总结
Vue构造函数的初始化大致是