[JavaScript] 纯文本查看 复制代码
class VueRouter {
constructor({ mode, routes }) {
this.mode = mode || 'hash'
this.routes = routes || []
// 格式化路由表 [] => {}
// [{path: '/home/, component: Home},{path: }] => {'/home': Home, '/about': About}
this.routesMap = this.createRoutesMap(this.routes)
// 需要记录一下当前路由状态
this.history = { current: null }
this.init()
}
init() {
// 判断模式
if (this.mode === 'hash') {
location.hash ? '' : location.hash = '#/'
window.addEventListener('load', () => {
this.history.current = location.hash.slice(1)
})
window.addEventListener('hashchange', () => {
this.history.current = location.hash.slice(1)
console.log('this.history', this.history)
})
} else {
location.pathname ? '' : location.pathname = '/'
window.addEventListener('load', () => {
console.log('load')
this.history.current = location.pathname
})
window.addEventListener('popstate', () => {
this.history.current = location.pathname
})
}
}
// 格式化路由表
createRoutesMap(routes) {
return routes.reduce((prev, current) => {
prev[current.path] = current.component
return prev
}, {})
}
}
// 使用use就会调用install方法
VueRouter.install = function (Vue) {
console.log('install')
// 每个组件都router得有 this.$router this.$route
// 在所有组件中如何拿到同一个路由的实例
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.router) {
// 根组件
this._root = this // 缓存一下当前实例
this._router = this.$options.router // 获取当前路由实例
Vue.util.defineReactive(this, 'abc', this._router.history)
} else {
// 父 -> 子 -> 孙
this._root = this.$parent._root
}
Object.defineProperty(this, '$router', { // VueRouter的实例
get() {
return this._root._router
}
})
Object.defineProperty(this, '$route', {
get() {
// 返回当前页面的状态
return {
current: this._root._router.history.current
}
}
})
}
})
Vue.component('router-link', {
props: {
to: {
type: String,
value: '/'
},
// tag: {
// String
// }
},
render(h) {
let mode = this._self._root._router.mode
// console.log(this._self._root)
// let tag = this.tag
return (
<a href={mode === 'hash' ? `#${this.to}` : this.to}>
{
this.$slots.default
}
</a>
)
}
})
Vue.component('router-view', {
render(h) {
let current = this._self._root._router.history.current
let routesMap = this._self._root._router.routesMap
return h(routesMap[current])
}
})
}
export default VueRouter