Vue-Router:Hash&History两种路由模式对比
本文最后更新于:8 个月前
Vue Router有两种路由模式:Hash和History,它们的实现原理各是怎样的呢?
Hash & History两种路由模式对比
一、Hash模式
核心:监听hashchange事件
定义
hash 模式是一种把前端路由的路径用井号
#
拼接在真实 URL 后面的模式。当井号#
后面的路径发生变化时,页面发生变化。优点
兼容性好
模拟示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<body>
<main>
<a href="#/a">A页面</a>
<a href="#/b">B页面</a>
<p>hash模式,当#后面的锚点发生变化时,会触发hashchange事件,可以通过监听该事件来实现路由跳转逻辑(点击链接,注意观察下面路径的变化)</p>
<div id="app"></div>
</main>
<script>
const app = document.getElementById('app')
function render() {
app.innerText = window.location.href
}
window.addEventListener('hashchange', render)
render()
</script>
</body>
二、History模式
核心:HTML5的History对象,监听popstate事件
定义
当path发生变化后,页面发生变化,但是不会重新发送请求。
利用的是HTML5 提供的 History API,开发者对路由进行修改,即更新浏览器 URL 地址,不会重新发起请求。
window.history对象保存了浏览器当前窗口的浏览历史
History对象有一个popstate事件,每当History对象发生改变时,就会触发这个事件(pushSate、replaceState方法除外)
模拟实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<body>
<main>
<h2>history模式</h2>
<a href="javascript:toA()">A页面</a>
<a href="javascript:toB()">B页面</a>
<div id="app"></div>
</main>
<script>
const app = document.getElementById('app')
function render() {
app.innerText = window.location.pathname
}
// pushState方法不会触发popstate事件,所以需要单独调用render
function toA() {
history.pushState({}, null, '/a')
render()
}
function toB() {
history.pushState({}, null, '/b')
render()
}
window.addEventListener('popstate', render)
render()
</script>
</body>需要借助web 框架来打开该页面,不能从本地直接打开,因为那样的话,跳转到路径会变成
本地/a
,无法正确访问到资源1
2npm install -g light-server
light-server -s . --historyindex '/history.html' --port 3000. --historyindex
表示如果后端资源不存在就返回history.html
的内容。浏览器刷新时,会按照路径发送真实的路径请求,如果这个路径恰好是 history API设置的话,服务端往往都是没有这个资源的,于是就返回404了。
所以线上部署 History路由模式 的 单页面应用时,需要后端配合,否则会请求不到资源而报错。以Nginx为例,需要在配置的 网页路径
location
下增加一行1
try_files $uri /index.html;
优点
路径看起来比较美观
缺点
(1)兼容性不如Hash模式好
(2)需要服务端支持,否则可能会404
验证:History API 不会重新发送请求
(1)下图是第一次请求页面的网络请求
(2)下图是点击了多次
A页面
、B页面
链接后的请求可以看到,调用 History API 改变页面 url 之后,并没有对页面重新请求,而是只对favicon.ico文件进行了请求!