流程图解
实现代码
JavaScript
JavaScript
// src/index.js
import { install } from './install' // 导入安装方法
...
export default class VueRouter {
...
}
...
VueRouter.install = install // 挂载安装方法,Vue.use 时自动调用 install 方法
// 1.用来避免将 Vue 做为依赖打包进来
export let Vue;
import RouterLink from './components/router-link';
import RouterView from './components/router-view';
const install = function (_Vue) {
if (install.installed && _Vue === Vue) return // 避免重复安装
install.installed = true
Vue = _Vue; // 将 Vue 构造函数存储起来
// 2.注册 router-view、router-link 全局组件
Vue.component('router-link', RouterLink);
Vue.component('router-view', RouterView);
// 3.全局混入将 router实例注册到了 new Vue,这样每个子组件都可以获取到 router 属性
Vue.mixin({
beforeCreate() { // mixin(当前options) 会调用 mergeOptions(全局Options,当前options) 进行合并
// 如果有 router 说明在根实例上增加了router实例,当前这个this实例是根实例
// 渲染流程先父后子,渲染完毕先子后父
if (this.$options.router) {
this._router = this.$options.router; // 将 router实例 挂载到根实例的 _router 上
this._routerRoot = this; // 将vm根实例放到了vm根实例的 _routerRoot 上
this._router.init(this); // 调用当前 router 实例中的 init 方法
// 若用户更改了 current 是没效果的,需要把 _route 也进行更新(history里面进行了更新)
// 将 _route 转成响应式的,_route 变化去更新视图
Vue.util.defineReactive(this, '_route', this._router.history.current);
} else {
// 孩子组件获取 _routerRoot,由于渲染流程先父后子,父亲一定先有 _routerRoot 属性
this._routerRoot = this.$parent && this.$parent._routerRoot;
}
// 这样所有的组件都拥有了 this._routerRoot、this._routerRoot._router 属性
}
});
// 4.添加实例属性:将 $route、$router 代理到 vm 实例上
Object.defineProperty(Vue.prototype, '$route', { // 存放的都是属性 path,matched
get() {
return this._routerRoot && this._routerRoot._route; // 取 current
}
})
Object.defineProperty(Vue.prototype, '$router', {
get() {
return this._routerRoot && this._routerRoot._router;
}
})
}
export default install;
打赏作者
您的打赏是我前进的动力
微信
支付宝
概览
上一篇
评论