let Vue;
class KVueRouter {
// 该参数 是new Router({routes})中的对象里面的配置
constructor(options) {
// 把参数缓存下来
this.$options = options;
//获取url上的hash
this.current = window.location.hash.slice(1) || '/';
//利用defineReactive()做响应式;
Vue.util.defineReactive(this, 'matched', []);
// 递归路由表;
this.match();
// Vue.util.defineReactive(this, 'current', initial);
window.addEventListener('hashchange', this.onHashChange.bind(this));
// window.addEventListener('load', this.onHashChange.bind(this));
}
// 嵌套路由的处理
onHashChange() {
this.current = window.location.hash.slice(1);
this.matched = [];
this.match();
}
match(routes) {
routes = routes || this.$options.routes;
for (const route of routes) {
if (route.path === '/' && this.current === '/') {
this.matched.push(route);
return;
}
if (route.path !== '/' && this.current.indexOf(route.path) != -1) {
this.matched.push(route);
if (route.children) {
this.match(route.children);
}
return;
}
}
}
}
// 参数1_Vue 是Vue的构造函数
KVueRouter.install = function(_Vue) {
Vue = _Vue; // 这样做的目的是打包插件的时候 不用打包Vue,因为用的都是插件使用传进来的参数
//挂载router实例,让所有的子组件都可以访问到 this.$router.push('/')
// Vue.use()会先执行install 方法,但是此时,并没有router实例;所以采用mixin全局混入的方式
Vue.mixin({
beforeCreate() {
// 判断有没有router实例 此时this是Vue实例
if (this.$options.router) {
Vue.prototype.$router = this.$options.router;
}
}
});
//实现两个全局组件
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
}
},
render(h) {
return h(
'a',
{
attrs: {
href: '#' + this.to
}
},
[this.$slots.default]
);
}
});
Vue.component('router-view', {
render(h) {
//标记当前router-view 深度
this.$vnode.data.routerView = true;
let depth = 0;
let parent = this.$parent;
while (parent) {
const vnodeData = parent.$vnode && parent.$vnode.data;
if (vnodeData) {
if (vnodeData.routerView) {
// 说明当前的parent是一个 router-view
depth++;
}
}
parent = parent.$parent;
}
let component = null;
const route = this.$router.matched[depth];
if (route) {
component = route.component;
}
return h(component);
}
});
};
export default KVueRouter;
0901-自定义路由插件
于 2020-09-06 22:51:05 首次发布