Vue-Router中有两种链接模式 hash
和 history
在表现形式上
- hash 在链接url前缀会加上
#
- history 更接近于常规的 url 链接,没有
#
在稳定性上
- hash 由于加上了
#
,用户在任意组件页面按F5刷新时,由于请求的仍然是当前页(index.html),所以不会有404的问题. - history 模式下,是真实的 url 表现形式.如果用户在任意页面刷新F5(非首页),一定会导致404问题(需后台配置设置将404跳转至index.html)
在实现形式上
- hash 是监听浏览器本身的 'hashchange' 事件来处理路由跳转逻辑.
- history 则是利用H5 history Api -> history.pushState() / history.replaceState / history.forward() / history.back() / history.go() 等,在实现路由跳转逻辑.
hash 模式下的路由跳转实现
处理逻辑图:
hash-route.png-
首先,将需要跳转的路由注册到tableRoute中.
-
监听 hashchange 函数,并将最新的hash url 设置在组件的url上.
-
组件的url在发生改变时,[由于url是响应式的],会自动调用render函数,重新渲染对应的组件.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hash-route</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
<script>
window.addEventListener('hashchange', () => {
// 触发setter,触发视图更新
vm.url = window.location.hash.slice(1)
})
const Foo = {
template: '<div>foo</div>'
}
const Bar = {
template: '<div>bar</div>'
}
const NotFound = { template: '<div>Not Found</div>' }
const routeTable = {
foo: Foo,
bar: Bar
}
const vm = new Vue({
el: '#app',
data: {
url: window.location.hash.slice(1),// **********************如果url不是响应式的则无法重新出发render函数.
},
// components: {
// Foo,
// Bar
// }, // 使用render 函数,不需要注册组件,直接将组件的options传递给h函数即可
render(h) {
return h("div", {}, [
// ************ render 里面依赖的url,url是响应式的. 当url发生改变时,内部的watcher会重新触发render component 函数
`当前hash值是:#${this.url}`,
h(routeTable[this.url] || NotFound),
h('a', { attrs: { href: '#foo' } }, 'foo'),
'|',
h('a', { attrs: { href: '#bar' } }, 'bar')
])
}
})
</script>
</html>
代码,直接复制,粘贴,就可以运行.
网友评论