文件入口
-
打开
package.json
,发现文件入口是"build": "node build/build.js",
-
找到
build
文件夹,发现加载的主要是config
文件夹中的内容 -
找到
config
文件,发现导出了一个数组,但是导出的并不是看到的数组,而是修改了的config
数组对象
function genConfig(opts) {
const config = {
input: {
// 文件入口
input: opts.input || resolve('src/index.js'),
// 插件配置
plugins: [
flow(),
node(),
cjs(),
replace({
__VERSION__: version
})
],
external: ['vue']
},
// 输出信息
output: {
file: opts.file,
format: opts.format,
banner,
name: 'VueRouter'
}
}
if (opts.env) {
config.input.plugins.unshift(
replace({
'process.env.NODE_ENV': JSON.stringify(opts.env)
})
)
}
if (opts.transpile !== false) {
config.input.plugins.push(buble())
}
// 最终的输出
return config
}
插件注册
根据index入口文件,找到 vueRouter 类
export default class VueRouter {
static install: () => void
...
...
}
我们看到vueRouter的第一个方法就是install函数,我们知道vue的插件基本都是需要install函数,才能使用vue.use注册。
原因如下,来到vue的源码
export function initUse(Vue: GlobalAPI) {
// vue.use是一个函数,里面传入一个plugin,可以是函数或者别的什么
Vue.use = function (plugin: Function | any) {
// 首先判断 是否已经有 plugin注册在vue上了,如果有就跳过,没有就初始化
const installedPlugins =
this._installedPlugins || (this._installedPlugins = [])
// 再次判断 当前函数 是否在 vue中注册过,如果注册了就直接返回,避免重复注册
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters use函数可能会接收到不止一个参数,取出除第一个参数之外的参数
const args = toArray(arguments, 1)
// 把vue排到第一位
args.unshift(this)
// 如果plugin有install函数,就执行install函数
if (isFunction(plugin.install)) {
plugin.install.apply(plugin, args)
// 插件本身就是个install函数
} else if (isFunction(plugin)) {
plugin.apply(null, args)
}
// 将plugin推入到installedPlugins
installedPlugins.push(plugin)
// 返回vue
return this
}
}
所以我们的vue-router中也必须包含install函数,才能注册到vue中
VueRouter的注册
VueRouter.install = install
转到install.js,看看在vue初始化之前都做了什么
beforeCreate() {
// options 获取Vue实例的自定义属性
// 在vue-router实例化时会将 router挂载到 vue的options里面
if (isDef(this.$options.router)) {
// 只有存在router,才会在vue上添加下面的属性
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
// 只有根实例才有 _routerRoot 属性,
// 因此如果当前实例不是根实例,那么它的父组件可能是根实例,
// 可以通过 this.$parent._routerRoot 访问到根实例的 _routerRoot 属性,
// 并将其赋值给当前实例的 _routerRoot 属性。如果当前实例的父组件也不是根实例,则会递归向上查找,直到找到根实例为止。
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
// 将实例注册到父级组件
registerInstance(this, this)
},
总结:如果想要在vue中注册我们的路由,首先需要的就是一个install函数,接收vue的功能,然后把自身的实例挂载到vue上。