浅析vue-router原理

2020-06-12 21:21:45易采站长站整理

history.replaceState({ key: _key }, '', url)
} else {
// 重新生成 key
_key = genKey()
// 带入新的 key 值
history.pushState({ key: _key }, '', url)
}
} catch (e) {
// 达到限制了 则重新指定新的地址
window.location[replace ? 'replace' : 'assign'](url)
}
}

replaceState
// 直接调用 pushState 传入 replace 为 true
export function replaceState (url?: string) {
pushState(url, true)
}

pushState和replaceState两种方法的共同特点:当调用他们修改浏览器历史栈后,虽然当前url改变了,但浏览器不会立即发送请求该url,这就为单页应用前端路由,更新视图但不重新请求页面提供了基础。


supportsPushState
export const supportsPushState = inBrowser && (function () {
const ua = window.navigator.userAgent
if (
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
ua.indexOf('Mobile Safari') !== -1 &&
ua.indexOf('Chrome') === -1 &&
ua.indexOf('Windows Phone') === -1
) {
return false
}
return window.history && 'pushState' in window.history
})()

其实所谓响应式属性,即当_route值改变时,会自动调用Vue实例的render()方法,更新视图。

$router.push()-->HashHistory.push()-->History.transitionTo()-->History.updateRoute()-->{app._route=route}-->vm.render()

监听地址栏

在浏览器中,用户可以直接在浏览器地址栏中输入改变路由,因此还需要监听浏览器地址栏中路由的变化 ,并具有与通过代码调用相同的响应行为,在HashHistory中这一功能通过setupListeners监听hashchange实现:


setupListeners () {
window.addEventListener('hashchange', () => {
if (!ensureSlash()) {
return
}
this.transitionTo(getHash(), route => {
replaceHash(route.fullPath)
})
})
}

HTML5History

History interface是浏览器历史记录栈提供的接口,通过back(),forward(),go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。


export class HTML5History extends History {
constructor (router: Router, base: ?string) {
super(router, base)
const expectScroll = router.options.scrollBehavior //指回滚方式
const supportsScroll = supportsPushState && expectScroll
if (supportsScroll) {
setupScroll()
}
const initLocation = getLocation(this.base)
//监控popstate事件
window.addEventListener('popstate', e => {
const current = this.current