持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 6 天,点击查看活动详情
2.Vue的来源
start
我最开始学习Vue.js的时候,在引入Vue.js之后,会通过 new Vue() 的方式来使用我们引入的Vue,那么这个 Vue是哪里来的呢?对应源码的出处是哪里?
我们怀着问题,去查看一下我们的 Vue项目
1. dev 命令
在 Vue项目的 package.json 中有 scripts 属性 ,script 中有一个 dev 属性,是这样的:
rollup -w -c scripts/config.js --environment TARGET:web-full-dev
看到这个命令有这么一个路径
scripts/config.js;我们去看看这个文件;
2. scripts/config.js
scripts/config.js
// 以下代码经过精简
// 7. builds[name] = builds['web-full-dev']
const builds = {
// Runtime+compiler development build (Browser)
'web-full-dev': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.js'),
format: 'umd',
env: 'development',
alias: { he: './entity-decoder' },
banner,
},
}
// 3. 归根到底,返回的就是 genConfig函数执行之后的返回值
function genConfig(name) {
// 6. 所有的数据来自 build
const opts = builds[name]
// 5. config本身是一个对象,对象的详细内容来自 opts
const config = {
input: opts.entry,
external: opts.external,
plugins: [flow(), alias(Object.assign({}, aliases, opts.alias))].concat(
opts.plugins || []
),
output: {
file: opts.dest,
format: opts.format,
banner: opts.banner,
name: opts.moduleName || 'Vue',
},
onwarn: (msg, warn) => {
if (!/Circular/.test(msg)) {
warn(msg)
}
},
}
// 4. 返回了 config
return config
}
// 1. 如果存储环境变量TARGET
if (process.env.TARGET) {
// 2. 导出 genConfig
module.exports = genConfig(process.env.TARGET)
} else {
exports.getBuild = genConfig
exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}
可以结合上述的注释,可以了解到:scripts/config.js 主要作用是返回一个配置对象。
运行dev命令的时候 ,由于还传入--environment TARGET:web-full-dev
所以返回了一个指定的配置对象;
'web-full-dev': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.js'),
format: 'umd',
env: 'development',
alias: { he: './entity-decoder' },
banner,
},
这个对象中有这么一个路径:
entry: resolve("web/entry-runtime-with-compiler.js"),
// entry 入口的意思
我们就沿着这个路径,开始去寻找 Vue 的来源。
这里的
resolve,代码如下,相当于在路径上拼接了这几个属性src/platfroms/
// resolve函数
const resolve = (p) => {
// "web/entry-runtime.js"
const base = p.split("/")[0]; // 第一个参数 例如 web server
// web并不是我们需要找到的文件路径,需要借助 aliases
if (aliases[base]) {
return path.resolve(aliases[base], p.slice(base.length + 1)); // resolve('src/platforms/web'),
} else {
return path.resolve(__dirname, "../", p);
}
};
// 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')
}
3. 查找文件
下面的示例,就是沿着文件的引入逻辑去寻找我们的 Vue出处:
3.1 src/platfroms/web/entry-runtime-with-compiler.js
import Vue from './runtime/index'
/* ... */
export default Vue
3.2 src/platfroms/web/runtime/index.js
import Vue from 'core/index'
/* ... */
export default Vue
3.3 src/core/index.js
import Vue from './instance/index'
/* ... */
export default Vue
3.4 src/core/instance/index.js
function Vue(options) {
// 判断是不是使用 new 关键词定义
if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue)) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
// 实例化时会调用 _init 方法
this._init(options)
}
export default Vue
沿着文件的引入逻辑,我们最终找到了 Vue的出处:在src/core/instance/index.js中定义。
写到这里,我们可以见到Vue的庐山真面目了
Vue本身是一个函数,在 new Vue()的时候,会执行 this._init方法。
end
- 本节主要记录了 Vue 在源码的出处。
- Vue 就是一个函数,在
new Vue()的时候,会执行this._init方法。