let _Vue = null
export default class VueRouter {
static install(Vue) {
if (VueRouter.install.installed) return
VueRouter.install.installed = true
_Vue = Vue
_Vue.mixin({
beforeCreate() {
if (this.$options.router) {
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options) {
this.options = options
this.options.mode = options.mode ? this.options.mode : 'history'
this.routeMap = {}
let defaultURL = this.getDefaultURL()
this.data = _Vue.observable({
current: defaultURL
})
}
init() {
this.createRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
createRouteMap() {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
initComponents(Vue) {
let self = this
Vue.component('router-link', {
props: {
to: {
type: String,
default: '/'
},
tag: {
type: String,
default: 'a'
}
},
render(h) {
return h(this.tag, {
attrs: {
href: this.to
},
on: {
click: (e) => {
// history.pushState(null, {}, this.to)
self.linkto(this.to)
e.preventDefault()
}
},
}, this.$slots.default)
}
})
Vue.component('router-view', {
render(h) {
return h(self.routeMap[self.data.current])
}
})
}
initEvent() {
window.addEventListener('popstate', () => {
this.data.current = window.location.pathname
})
}
linkto(to) {
switch (this.options.mode) {
case 'hash':
location.hash = to
this.data.current = to
break;
case 'history':
self.data.current = this.to
history.pushState(null, {}, to)
break;
}
}
getDefaultURL() {
if (this.options.mode === 'history')
return window.location.pathname || '/'
else if (this.options.mode === 'hash') {
window.addEventListener('hashchange', () => {
this.data.current = location.hash.substr(1)
})
if (location.hash) return location.hash.substr(1)
else {
location.hash = '/'
return '/'
}
}
}
}