let _Vue;
class HTML5History {
constructor (route, base) {
this.current = '';
this.app = new _Vue({
data() {
return {
path: '/'
}
},
})
}
setupListeners() {
const handleRoutingEvent = () => {
this.current = location.pathname?.slice(1) || '/';
this.app.path = this.current;
}
window.addEventListener(
'popstate',
handleRoutingEvent
)
}
push (path) {
history.pushState({}, '', path);
this.app.path = path;
}
}
class HashHistory {
constructor (route, base) {
this.current = '';
this.app = new _Vue({
data() {
return {
path: '/'
}
},
})
}
setupListeners() {
const handleRoutingEvent = () => {
this.current = location.hash?.slice(1) || '/';
this.app.path = this.current;
}
window.addEventListener(
'hashchange',
handleRoutingEvent
)
}
push (location) {
window.location.hash = location
}
}
class Router {
constructor(options) {
this.options = options;
let mode = options.mode || 'hash';
this.routes = options.routes;
switch (mode) {
case 'history':
this.history = new HTML5History(this, options.base)
break
case 'hash':
this.history = new HashHistory(this, options.base, this.fallback)
break
default:
}
}
init() {
this.history.setupListeners()
}
push (location) {
this.history.push(location)
}
}
Router.install = function(Vue) {
_Vue = Vue;
Vue.mixin({
beforeCreate () {
if (this.$options.router) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
}
})
Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
})
Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})
Vue.component('router-view',{
render(h){
const path = this._routerRoot._router.history.app.path;
const routes = this._routerRoot._router.routes;
const route = routes.find((i) => i.path === `/${path}`)
const com = route ? route.component : routes.find((i) => i.path === `/404`).component
return h(com)
}
})
}
export default Router;
参考文章
history
vue-router