# VueRouter 插件的安装
vue-router做为vue的官方插件,使用Vue.use方法来进行安装,而Vue.use方法实际是调用了组件的install方法,这个方法定义在项目的src/install.js文件中
export function install(Vue) {
if (install.installed && _Vue === Vue) return;
install.installed = true;
_Vue = Vue;
const isDef = (v) => v !== undefined;
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode;
if (
isDef(i) &&
isDef((i = i.data)) &&
isDef((i = i.registerRouteInstance))
) {
i(vm, callVal);
}
};
Vue.mixin({
beforeCreate() {
if (isDef(this.$options.router)) {
this._routerRoot = this;
this._router = this.$options.router;
this._router.init(this);
Vue.util.defineReactive(this, '_route', this._router.history.current);
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
}
registerInstance(this, this);
},
destroyed() {
registerInstance(this);
},
});
Object.defineProperty(Vue.prototype, '$router', {
get() {
return this._routerRoot._router;
},
});
Object.defineProperty(Vue.prototype, '$route', {
get() {
return this._routerRoot._route;
},
});
Vue.component('RouterView', View);
Vue.component('RouterLink', Link);
const strats = Vue.config.optionMergeStrategies;
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter =
strats.beforeRouteLeave =
strats.beforeRouteUpdate =
strats.created;
}
代码的核心逻辑分 3 点
- 调用
Vue.mixin混入 2 个生命周期钩子 - 在
Vue的原型对象Vue.prototype中定义了$route$router2 个属性 - 全局注册了
RouterViewRouterLink2 个组件
# 生命周期钩子
beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this, this)
},
destroyed () {
registerInstance(this)
}
这段代码首先判断了当前vue实例的$options对象上有无router属性,如有,则说明该实例是vue的根实例。初始化属性_routerRoot为当前vue根实例,接着为根实例添加_router route属性,再调用router对象的init方法,init方法我们后面再分析。若当前实例不是根实例,则从父组件上获取到根路由对象并赋值。接着调用registerInstance方法
const registerInstance = (vm, callVal) => {
let i = vm.$options._parentVnode;
if (isDef(i) && isDef((i = i.data)) && isDef((i = i.registerRouteInstance))) {
i(vm, callVal);
}
};
这个方法是调用定义在父组件vnode上的registerRouteInstance方法,这是router-view组件中定义的方法,后面在具体分析
destroyed钩子也是调用了registerInstance方法,后面分析组件在提
# $router & $route
由代码得知,这2个属性其实就是当前vue根实例上的2个属性,分别指向根实例的_router _route属性。他们的关系是$router.history.current === $route,$router 其实就是VueRouter这个对象的实例
# 全局组件
后面说到路由组件再具体分析
# 其他
install方法的最后对beforeRouteEnter beforeRouteLeave beforeRouteUpdate 这 3 个组件内的路由钩子的合并策略做了初始化。完全等同于 created 钩子的合并策略
# 总结
install 的方法很简单
- 首先全局混入了
beforeCreate和destroyed2 个生命周期钩子,负责处理路由相关的属性初始化和实例的注册和销毁 - 暴露了 2 个
vue组件属性$route$router方便我们使用 - 全局注册了
router-viewrouter-link2 个组件 - 对
beforeRouteEnterbeforeRouteLeavebeforeRouteUpdate这 3 个组件内的路由钩子的合并策略做了初始化
← 组件的挂载 Router 对象实例化 →