手写VueRouter
需求分析
- spa页面不能刷新
- hash eg: #/about
- History api eg: /about
- 根据url显示对应内容
- router-view
- 数据响应式:current变量持有url地址,一旦变化,动态重新执行render
任务
- 实现一个插件
- 实现VueRouter类
- 处理路由选项
- 监控url变化,hashchange
- 响应这个变化
- 实现install方法
let _Vue
class VueRouter {
constructor(options) {
this.$options = options
this.routeMap = {}
this.$options.routes.forEach(route => {
this.routeMap[route.path] = route
});
const initial = window.location.hash.slice(1) || '/'
_Vue.util.defineReactive(this, 'current', initial)
window.addEventListener('hashchange', this.onHashChange.bind(this))
}
onHashChange(){
this.current = window.location.hash.slice(1)
console.log(this.current);
}
}
VueRouter.install = function (Vue) {
_Vue = Vue
Vue.mixin({
beforeCreate() {
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
},
})
Vue.component('router-link', {
props: {
to: {
type: String,
require: true
}
},
render(h) {
return h('a',{
attrs:{
href: '#' + this.to
}
}, this.$slots.default)
},
})
Vue.component('router-view', {
render(h) {
const {routeMap, current} = this.$router
let component = routeMap[current] ? routeMap[current].component : null
const route = this.$router.$options.routes.find(
route => route.path === this.$router.current
)
console.log(route,'route');
if(route){
component = route.component
}
return h(component)
}
})
}
export default VueRouter
代码截图


