分类

  • hash

hash 是通过锚点链接(#)来实现的, 锚点不会向服务端发送请求。
我们可以通过 location 相关 api 控制浏览器记录修改,hashchange 事件,监听地址栏锚点地址,重新渲染路由视图

1
window.addEventListener("hashchange", funcRef, false);
  • history

html5 新增的 api,history 会向服务器发送请求。
我们可以通过 pushState、replaceState 对浏览器历史记录修改,popState 事件监听状态变更,重新渲染路由

1
2
3
4
5
history.pushState()
history.replaceState()
history.go()
history.back() 等价于 history.go(-1)
history.forward() 则等价于 history.go(1)

区别

1.直观区别:

hash 模式 url 带#号,history 模式不带#号。

2.深层区别:

hash 模式 url 里面永远带着#号,我们在开发当中默认使用这个模式。
如果用户考虑 url 的规范那么就需要使用 history 模式,因为 history 模式没有#号,是个正常的 url 适合推广宣传
功能也有区别,比如我们在开发 app 的时候有分享页面,那么这个分享出去的页面就是用 vue 或是 react 做的,
咱们把这个页面分享到第三方的 app 里,有的 app 里面 url 是不允许带有#号的,所以要将#号去除那么就要使用

路由模式配置:

1
2
3
4
5
export default new Router({
// mode: 'history',
mode: "hash",
routes,
});

history api 可以分为两大部分,切换和修改,参考 MDN,切换历史状态包括 back、forward、go 三个方法,对应浏览器的前进,后退,跳转操作,有同学说了,(谷歌)浏览器只有前进和后退,没有跳转,嗯,在前进后退上长按鼠标,会出来所有当前窗口的历史记录,从而可以跳转(也许叫跳更合适):

1
2
3
4
history.go(-2); //后退两次
history.go(2); //前进两次
history.back(); //后退
hsitory.forward(); //前进

修改历史状态包括了 pushState,replaceState

两个方法,这两个方法接收三个参数:stateObj,title,url

1
2
3
4
5
6
7
8
9
10
11
history.pushState({ color: "red" }, "red", "red");
history.back();
setTimeout(function () {
history.forward();
}, 0);
window.onpopstate = function (event) {
console.log(event.state);
if (event.state && event.state.color === "red") {
document.body.style.color = "red";
}
};

通过 pushstate 把页面的状态保存在 state 对象中,当页面的 url 再变回这个 url 时,可以通过 event.state 取到这个 state 对象,从而可以对页面状态进行还原,这里的页面状态就是页面字体颜色,其实滚动条的位置,阅读进度,组件的开关的这些页面状态都可以存储到 state 的里面。

history 模式的问题

通过 history api,我们丢掉了丑陋的#,但是它也有个问题:不怕前进,不怕后退,就怕刷新f5,(如果后端没有准备的话),因为刷新是实实在在地去请求服务器的,不玩虚的。 在 hash 模式下,前端路由修改的是#中的信息,而浏览器请求时是不带它玩的,所以没有问题.但是在 history 下,你可以自由的修改 path,当刷新时,如果服务器中没有相应的响应或者资源,会分分钟刷出一个 404 来。