import Vue from 'vue';
export default class MyRouter {
constructor(config) {
// 保存路由数据
this.routers = config.routes;
// 保存转换后的路由信息
this.routersMap = this.getRoutersMap(config.routes);
// 转换为响应式数据,保存当前路由路径
Vue.util.defineReactive(this, 'currentPath', '');
// 初始化
this.initRouter();
}
initRouter() {
// 1.初始化获取当前页面地址
this.getCurrentPath();
// 2.监听路由地址变化
window.onhashchange = () => {
this.getCurrentPath();
};
}
// 获取 { [path]: [component] } 形式的路由数据
getRoutersMap(routes) {
return routes.reduce((memo, curr) => {
memo[curr.path] = curr.component;
return memo;
}, {});
}
// 获取当前页面地址
getCurrentPath() {
this.currentPath = window.location.hash.slice(1) || '/';
}
}
// Vue.use 时执行
MyRouter.install = function (Vue) {
// 在 Vue 原型挂载 $router,使用 mixin 延迟到组件构建之后执行, 否则获取不到 this.$options
Vue.mixin({
created() {
// 只有在 this.$options.router 存在时赋值给 $router,此时 this 代表的是根组件,因为根组件才含有 router 选项
if (this.$options.router) {
this._root = this;
Vue.prototype.$router = this.$options.router;
// 保证 $router 不能被修改
Object.defineProperty(Vue.prototype, '$router', {
writable: false
});
} else {
// 让所有的子组件都指向共同的根组件实例
this._root = this.$parent._root;
}
}
});
// 注册 router-link
Vue.component("router-link", {
props: {
"to": String
},
// template: `<a :href="to" class="my-router-link"><slot></slot></a>`,
render(h) {
return h('a', {
attrs: {
href: `#${this.to}`,
},
class: "my-router-link",
}, this.$slots.default)
},
});
// 注册 router-view
Vue.component("router-view", {
render(h) {
if (this.$router) {
return h(this.$router.routersMap[this.$router.currentPath]);
} else {
return null;
}
}
});
};