一、例子中引用的dist目录下的vue.js源文件入口
上一篇重读Vue源码系列二 —— 如何调试Vue源码中详细介绍了vue.js的生成过程,并且我们知道了vue.js源码的入口文件就是web/entry-runtime-with-compiler.js,真实的路径是src/platforms/web/entry-runtime-with-compiler.js。
const builds = {
// Runtime+compiler production build (Browser)
'web-full-prod': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.min.js'),
format: 'umd',
env: 'production',
alias: { he: './entity-decoder' },
banner
}
}
这样我们就可以沿着入口文件去查找Vue的构造函数了。
二、Vue构造函数到底在哪里?
- 我们从入口
src/platforms/web/entry-runtime-with-compiler.js开始查找,在该文件我们看到了这行代码import Vue from './runtime/index', 且把Vueexport出去了, 这其实也是我们平常使用的new Vue()的Vue对象,但是在这个文件并没有发现Vue构造函数的定义。
// /src/platforms/web/entry-runtime-with-compiler.js
import config from 'core/config'
import { warn, cached } from 'core/util/index'
import { mark, measure } from 'core/util/perf'
import Vue from './runtime/index' //vue构造函数
import { query } from './util/index'
import { compileToFunctions } from './compiler/index'
import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat'
此处省略......
//最后export出去
export default Vue
- 沿着
import Vue from './runtime/index'继续查找,在这里也没有发现Vue构造函数的定义,但是我们看到了Vue是从'core/index'引进来的。
/src/platforms/web/runtime/index.js
import Vue from 'core/index'
- 继续沿着
import Vue from 'core/index'查找,如果对webpack熟悉的话,会知道'core/index'使用的是alias,方便我们引入文件,我们找到webpack的配置文件/vue/scripts/alias.js。
module.exports = {
vue: resolve('src/platforms/web/entry-runtime-with-compiler'),
compiler: resolve('src/compiler'),
core: resolve('src/core'),
shared: resolve('src/shared'),
web: resolve('src/platforms/web'),
weex: resolve('src/platforms/weex'),
server: resolve('src/server'),
sfc: resolve('src/sfc')
}
'core/index'其实就是'src/core/index'。
// src/core/index
import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
这个文件还是没有Vue的构造函数,我们继续沿着import Vue from './instance/index'查找
- 继续查找
'./instance/index'文件
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {//options就是我们new Vue(options)中的option
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)
}
console.info(`=====Vue最原始构造函数,此时一无所有`);
initMixin(Vue) //prototype_init 传递Vue的目的是为了共用一个Vue类
console.info(`=====VueinitMixin Finish Vue.prototype._init=`,Vue.prototype._init);
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue) //原型添加$nextSick,_render
console.log(`core instance index.js`);
export default Vue
这样,我们在这里终于找到了Vue的构造函数,但是会发现它真的是一无所有,里面就一行看不懂的代码 this._init(options),那我们平时用的那么多的全局API、生命周期钩子、实例方法等都在哪定义的呢?
我们将会在接下来的文章一一介绍~
三、总结
通过前两篇重读Vue源码系列一 —— 目录结构、重读Vue源码系列二 —— 如何调试Vue源码以及本篇文章的介绍,我们对Vue源码的目录结构、Vue.js的构建过程以及Vue构造函数的定义都有了基本了解,也找到了Vue的构造函数的源头。
function Vue (options) {//options就是我们new Vue(options)中的option
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对象,最终成为我们使用Vue。
下一篇将会介绍重读Vue源码系列四—— “一无所有”的Vue如何实现全局API以及实例属性以及后续的源码讲解计划~