class HistoryRoute {
constructor() {
this.current = null
}
}
class VueRouter {
constructor(options) {
this.mode = options.mode || 'hash'
this.routes = options.routes || []
this.routesMap = this.createMap(this.routes)
this.history = new HistoryRoute()
this.init()
}
init() {
if (this.mode === 'hash') {
if (!location.hash) {
location.hash = '/'
}
window.addEventListener('load', () => {
console.log('load')
this.history.current = location.hash.slice(1)
})
window.addEventListener('hashchange', () => {
console.log('hashchange')
this.history.current = location.hash.slice(1)
})
} else {
if (location.hash) {
location.pathname = '/'
}
window.addEventListener('load', () => {
console.log('load')
this.history.current = location.pathname
})
window.addEventListener('popstate', () => {
console.log('popstate')
this.history.current = location.pathname
})
}
}
createMap(routes) {
return routes.reduce((memo, current) => {
memo[current.path] = current.component
return memo
}, {})
}
go() {
}
push(path) {
window.history.pushState({}, '', path)
this.history.current = path
}
back() {
}
afterEach() {
console.log('after')
}
beforeEach() {
}
}
VueRouter.install = function (Vue) {
console.log(Vue, 'install')
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.router) { // 定位根组件
this._root = this
this._router = this.$options.router
Vue.util.defineReactive(this, 'xxx', this._router.history)
} else { // 子节点
try {
this._root = this.$parent._root
} catch (e) {
console.log(this, e)
}
}
Object.defineProperty(this, '$router', {
get() {
return this._root._router
}
})
Object.defineProperty(this, '$route', {
get() {
return {
current: this._root._router.history.current
}
}
})
}
})
Vue.component('router-link', {
props: {
to: String,
tag: String
},
render(h) {
let mode = this._self._root._router.mode
let tag = this.tag || 'a'
console.log(this)
return h(tag, {
attrs: {
href: this._self._root._router.mode === 'hash' ? `#${this.to}` : this.to,
},
on: {
click: () => {
this.handleClick()
}
}
}, this.$slots.default)
},
methods: {
handleClick() {
this._root._router.push(this.to)
event.returnValue = false
}
}
})
Vue.component('router-view', {
render(h) {
let current = this._self._root._router.history.current
let routeMap = this._self._root._router.routesMap
console.log(this)
return h(routeMap[current])
}
})
}
export default VueRouter
网友评论