import View from './components/view'
import Link from './components/link'
//用于保存创建 vue 的实力。
export let _Vue
/**
* import VueRouter from 'vur-router'
* Vue.use(VueRouter) 的时候就调用该 install 方法。
*
* 注意点: 虽然 install 方法会在 router 创建之前就被调用。但是被混合的方法 {
* beforeCreate(){xxxx}
* destroyed(){ xxxx }
* } 是在 router 实例创建之后执行的。
*
*/
export function install(Vue) {
//如果 install 方法中已经存在 installed 标记,且是上次记录的 vue 实例,则直接返回。
if (install.installed && _Vue === Vue) return
//设置 installed 标记,表示已经走过了 VueRouter.install 流程。
install.installed = true
//获取 vue 实例。
_Vue = Vue
//判断实例 v 是否存在。
const isDef = (v) => v !== undefined
/*
registerInstance()
第一个参数: vm 实例。
第二个参数: vm 实例 或者 undefined。
*/
const registerInstance = (vm, callVal) => {
//获取 parentNode.
let i = vm.$options._parentVnode
//如果 parentNode 实例存在,且 vue.data 也存在,且 vue.registerRouteInstance() 方法也存在。则调用 registerRouteInstance() 方法。
// 第一个参数是 vm 实例;
// 第二个参数: vm 实例 或者 undefined。
if (
isDef(i) &&
isDef((i = i.data)) &&
isDef((i = i.registerRouteInstance))
) {
i(vm, callVal)
}
}
//每当创建一个 vue 实例的时候,都在这个 vue 实例中混合两个生命周期方法。
// beforeCreate(){ ... }
// destroyed(){ ... }
Vue.mixin({
beforeCreate() {
//$options 就是 new Vue(options) 中的 options 参数。
//如果当前 vue 实例传入的 options 属性中存在 router 属性。
//一般而言,根 vue 实例会走 if 代码块流程。子 vue 实例会走 else 代码块流程。
if (isDef(this.$options.router)) {
//vue 实例中使用 _routerRoot 属性指向 vue 实例。注意 this 是正在创建的 vue 实例。
this._routerRoot = this
//vue 实例中使用 _router 属性指向 router 实例。
this._router = this.$options.router
//调用 router 实例的 init() 方法。
this._router.init(this)
//
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
//一般而言,子 vue 实例会走 else 代码块流程。
//判断 parentNode 是否存在,如果存在就获取 parentNode 的 router。如果为false,则将 this._routerRoot 指向自身 vue 实例。
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
//将第二个参数 this, 注册到 route.matched[depth].instances 中。
registerInstance(this, this)
},
destroyed() {
//当第二个参数为 undefined 的时候,相当于用undefined 覆盖了之前注册的this。相当于是注销。
registerInstance(this)
},
})
/**
* 在 vue 的原型上增加 '$router' 属性,用于获取当前 vue上绑定的 router 实例。
* 根据 install 方法的代码可以知道,不同的 vue 实例其实是可以挂不同的 router 实例的。
*/
Object.defineProperty(Vue.prototype, '$router', {
get() {
//router 是 vue-router 的导航对象。
return this._routerRoot._router
},
})
/*
在 vue 的原型上增加 '$route' 属性,用于获取当前 vue 上绑定的 route 实例。
*/
Object.defineProperty(Vue.prototype, '$route', {
get() {
//route 是用来存储 vue-router 导航数据的实例。
return this._routerRoot._route
},
})
//注入全局组件 <router-view>
Vue.component('RouterView', View)
//注入全局组件 <router-link>
Vue.component('RouterLink', Link)
/*
Vue.config.optionMergeStrategies 对应的是 vue.config.js 的配置。
用于表示 options 数据的合并策略。
*/
const strats = Vue.config.optionMergeStrategies
// use the same hook merging strategy for route hooks
//router 的钩子函数都使用与 vue.created 一样的mixin 合并策略。
// strats.beforeRouteEnter 指定 router.beforeRouteEnter 的混合策略。
// strats.beforeRouteLeave 指定 router.beforeRouteLeave 的混合策略。
// strats.beforeRouteUpdate 指定 router.beforeRouteUpdate 的混合策略。
// strats.created 指定 vue.created 的混合策略。
strats.beforeRouteEnter =
strats.beforeRouteLeave =
strats.beforeRouteUpdate =
strats.created
}
vue-router3源码注释系列 /src/install.js
于 2022-03-21 10:26:27 首次发布