initEvent
还有一个问题,现在当我们点击浏览器的前进后退按钮的时候,浏览器地址变化了,但是 router-view 的内容却没有变化,这就需要我们监听 popState 事件。
调用
history.pushState()或者history.replaceState()不会触发popstate事件。popstate事件只会在浏览器某些行为下触发,比如点击后退按钮(或者在 JavaScript 中调用history.back()方法)。即,在同一文档的两个历史记录条目之间导航会触发该事件。
initEvent() {
window.addEventListener("popstate", () => {
this.data.current = window.location.pathname
})
}
模拟 VueRouter 完整代码
/* eslint-disable */
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
}
}
})
}
constructor(options) {
this.options = options
this.routeMap = {}
this.data = _Vue.observable({
current: "/"
})
this.init()
}
init() {
this.createRouteMap()
this.initComponent(_Vue)
this.initEvent()
}
createRouteMap() {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
});
}
initComponent(Vue) {
const self = this
Vue.component("router-link", {
props: {
to: String
},
render(h) {
return h("a", {
attrs: {
href: ''
},
on: {
click: this.clickhander
}
}, [this.$slots.default])
},
methods: {
clickhander(e) {
history.pushState({}, "", this.to)
self.data.current = this.to
e.preventDefault()
}
}
})
Vue.component("router-view", {
render(h) {
const cm = self.routeMap[self.data.current]
return h(cm)
}
})
}
initEvent() {
window.addEventListener("popstate", () => {
this.data.current = window.location.pathname
})
}
}