Vue vue-router简单实现
2021-01-06 本文已影响0人
爱吃馒头不吃辣
// 1.创建VueRouter类
let Vue
class VueRouter {
constructor(options) {
// 6.存储路由配置信息
this.$opt = options;
// 18.存储当前路由
this.current = window.location.hash.slice(1) || '/';
// 19.新建响应式属性matched,记录路由映射关系
Vue.util.defineReactive(this, 'matched', []);
// 20.match方法可以递归遍历路由表,获取匹配关系
this.match();
// 24.监听路由变化
window.addEventListener('hashchange', () => {
this.current = window.location.hash.slice(1) || '/';
// 25.每次路由变化映射表指控重新获取
this.matched = [];
this.match();
})
}
match(routers) {
routers = routers || this.$opt.routes;
// 21.遍历路由将当前路由存储到matched映射关系数组中
for (const route of routers) {
// 22.如果当前是根目录直接存入映射关系中
if (route.path === '/' && this.current === '/') {
this.matched.push(route);
return;
}
// 23.非根目录情况下,获取其嵌套路由。递归存入
if (route.path !== '/' && this.current.indexOf(route.path) != -1) {
this.matched.push(route)
if (route.children) {
this.match(route.children)
}
return;
}
}
}
}
// 3.实现install插件方法,install真正的执行者是Vue.use(VueRouter),所以此处的形参_Vue就是Vue的构造函数
VueRouter.install = function (_Vue) {
Vue = _Vue
// 4.在Vue原型挂载$router,使用mixin延迟到组件构建之后执行不然获取不到this.$options
Vue.mixin({
beforeCreate() {
// 5.只有在this.$options.router存在时赋值给$router,因为在生命周期内,this指的是Vue组件实例
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
},
})
// 7.实现router-link
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
},
},
// 8.router-link的本质其实就是<a href='#/about'></a>
render(h) {
// 9.这里的this指的是router-link组件实例
return h('a', {
attrs: {
href: `#${this.to}`
}
}, this.$slots.default);
},
})
// 10.实现router-view,本质就是将路由匹配的component加载出来
Vue.component('router-view', {
// 11.涉及到嵌套路由
render(h) {
// 12.标记当前router-view的深度,标记自己是个routerView
this.$vnode.data.routerView = true;
// 13.记录深度
let depth = 0;
// 14.获取父元素
let parent = this.$parent;
// 15.判断是不是routerView,不停循环向上去找
while (parent) {
// 16.需要从$vnode.data中获取routerView,先判断是否存在
const vnodeData = parent.$vnode && parent.$vnode.data
if (vnodeData) {
if (vnodeData.routerView) {
// 17.所有条件都满足,说明parent是一个router-view
depth++
}
}
// 16.赋值新的父元素
parent = parent.$parent
}
let component = null;
// 24.根据深度获取路由信息
let router = this.$router.matched[depth];
if (router) {
component = router.component
}
return h(component)
},
})
}
// 2.导出VueRouter
export default VueRouter