/*
需求分析:
1、vueRouter类和install方法
2、全局组件 router-view (显示内容)和 router-link(用于跳转)
3、监控url的变化, hashchange或popstate
4、响应最新url:创建一个响应current,,当它改变获取对应组件并显示
*/
第一步:vueRouter类和install方法
// 1.实现一个Router类并挂载期实例
let Vue;
class VueRouter {
constructor(options) {
this.$options = options;
if(options.mode){
console.log(options.mode)
}
}
}
// 插件需要实现install方法
VueRouter.install = function (_Vue) {
// 保存Vue构造函数在VueRouter中使用
Vue = _Vue;
// 任务1:使用混入来做router挂载这件事情
Vue.mixin({
beforeCreate() {
// 只有根实例才有router选项
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
})
}
第二步:组件
Vue.component('router-link',
props: {
to: {
type: String,
required: true
},
},
render(h) {
// h(tag, props, children)
return h('a',
{ attrs: { href: '#' + this.to } },
this.$slots.default
)
})
Vue.component('router-view', {
render(h) {
}
}))
第三步 :定义响应式的current属性,监控url的变化,hashchange或popstate,
construct(){
/*
Vue.util.defineReactive, 这是Vue里面观察者劫持数据的方法,
劫持_route,当_route触发setter方法的时候,则会通知到依赖的组件。
*/
Vue.util.defineReactive(this, 'current', '' )
// 请确保onHashChange中this指向当前实例
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
onHashChange() {
console.log(window.location.hash);
this.current = window.location.hash.slice(1) || '/'
}
}
第四步:提前处理路由表
// 缓存path和route映射关系
this.routeMap = {}
this.$options.routes.forEach(route => {
this.routeMap[route.path] = route
});
第五步:更新组件
vueRouter
render(h) {
// 根据current获取组件并render
// current怎么获取?
// console.log('render',this.$router.current);
// 获取要渲染的组件
let component = null
const { routeMap, current } = this.$router
if (routeMap[current]) {
component = routeMap[current].component
}
return h(component)
}
参考链接