vue-router 实现 -- HTML5History
muwoo opened this issue · 0 comments
vue-router
通过设置mode = history
可以在浏览器支持 history 模式的情况下,用来开启 HTML5History 模式。我们知道在install
挂载的时候,会在beforeCreate
钩子内执行init
方法:
init () {
// ...
if (history instanceof HTML5History) {
history.transitionTo(history.getCurrentLocation())
}
// ...
}
当判断当前模式是 HTML5History
的时候,会执行 history
对象上的 transitionTo
方法。接下来我们主要分析 HTML5History 的主要功能。
constructor
在vue-router
实例化过程中,执行对 HTML5History 的实例化:
this.history = new HTML5History(this, options.base)
此时会执行 HTML5History 中的 constructor
:
constructor (router: Router, base: ?string) {
// 实现 base 基类中的构造函数
super(router, base)
// 滚动信息处理
const expectScroll = router.options.scrollBehavior
const supportsScroll = supportsPushState && expectScroll
if (supportsScroll) {
setupScroll()
}
const initLocation = getLocation(this.base)
window.addEventListener('popstate', e => {
const current = this.current
// 避免在有的浏览器中第一次加载路由就会触发 `popstate` 事件
const location = getLocation(this.base)
if (this.current === START && location === initLocation) {
return
}
// 执行跳转动作
this.transitionTo(location, route => {
if (supportsScroll) {
handleScroll(router, route, current, true)
}
})
})
}
可以看到在这种模式下,初始化作的工作相比 hash
模式少了很多,只是调用基类构造函数以及初始化监听事件,不需要再做额外的工作。由于在上篇文章中已经介绍了 transitionTo
和confirmTransition
。这里不再过多介绍了。到这里好像也就没什么,那么我们来看几个之前没介绍的一下 API 吧
一些API
在 vue-router
中我们通常会通过这种方式操作路由信息:
router.push(location, onComplete?, onAbort?)
router.replace(location, onComplete?, onAbort?)
router.go(n)
router.back()
router.forward()
具体的可以参考这里编程式导航
来一起看一下 vue-router
的统一实现:
push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
this.history.push(location, onComplete, onAbort)
}
replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
this.history.replace(location, onComplete, onAbort)
}
go (n: number) {
this.history.go(n)
}
back () {
this.go(-1)
}
forward () {
this.go(1)
}
可以看到,也都是调用了history
内部的方法。
你也许注意到
router.push
、router.replace
和router.go
跟window.history.pushState
、window.history.replaceState
和window.history.go
好像, 实际上它们确实是效仿window.history API
的。
因此,如果你已经熟悉Browser History APIs
,那么在 Vue Router 中操作 history 就是超级简单的。
还有值得提及的,Vue Router 的导航方法 (push、 replace、 go
) 在各类路由模式 (history、 hash 和 abstract
) 下表现一致。
举个例子
// go
go (n: number) {
window.history.go(n)
}
// push最终也是调用的history API
history.pushState({ key: _key }, '', url)