class VueRouter {
constructor(options) {
this.mode = options.mode || 'hash'
this.routes = options.routes || []
this.init()
this.current = { path: '' }
this.routerMap = this.collectRouterMap(this.routes)
}
init() {
if (this.mode === 'hash') {
location.hash ? '' : location.hash = '/'
window.addEventListener('load', () => {
this.current.path = location.hash.slice(1)
})
window.addEventListener('hashchange', () => {
this.current.path = location.hash.slice(1)
})
} else {
location.pathname ? '' : location.pathname = '/'
window.addEventListener('load', () => {
this.current.path = location.pathname
})
window.addEventListener('popstate', () => {
this.current.path = location.pathname
})
}
}
collectRouterMap(routes) {
return routes.reduce((obj, cur) => {
obj[cur.path] = cur.component
return obj
}, {})
}
}
VueRouter.install = function (Vue, opts) {
// 给全部组件添加$router
Vue.mixin({
// 把$router和$route挂载在全部组件上
beforeCreate() {
if (this.$options && this.$options.router) {
this._root = this
this._router = this.$options.router
Vue.util.defineReactive(this, '', this._router.current)
} else {
this._root = this.$parent._root
}
Object.defineProperty(this, '$router', {
get() {
return this._root._router
}
})
Object.defineProperty(this, '$route', {
get() {
return this._root.router.history.current.path
}
})
}
})
Vue.component('router-link', {
props: {
to: String
},
methods: {
push(path) {
history.pushState({}, null, path)
this._self._root.$options.router.current.path = path
},
},
render() {
let mode = this._self._root.$options.router.mode
if (mode === 'hash') {
return <a href={`#${this.to}`}>{this.$slots.default}</a>
} else {
return <a onClick={() => { this.push(this.to) }}>{this.$slots.default}</a>
}
}
})
Vue.component('router-view', {
render(h) {
let current = this._self._root.$options.router.current.path
let routerMap = this._self._root.$options.router.routerMap
let compoennt = routerMap[current]
return h(compoennt)
}
})
}
export default VueRouter
Vue-Router手写实现
最新推荐文章于 2024-07-25 11:00:49 发布