window.history.pushState你用对了吗?

Posted by gyn on 2021-11-13

在React项目中,我们使用react-route-dom的钩子函数去处理React组件中路由的跳转,而在非React组件中,我们还是会用到window.historywindow.location去处理页面跳转的情况。

在我的一个项目中,使用了Axios的拦截器去统一处理API的返回:若API返回信息是用户登录信息超时,则跳转到登录页面。代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
axios.interceptors.response.use(
(response) => {
// 示例代码
const resStatus = response.status
if (resStatus === TIMEOUT) {
// 跳转到login页面
window.history.pushState(null, '', '/#/login');
window.history.go();
}
}
)

localhost开发和测试时,能够正常跳转,但在测试环境下,跳转会出现问题。测试环境下,前端资源的整体路径是:https://domainname/folder1/folder2/foloder3/index.html,打开后没有跳转到https://domainname/folder1/folder2/foloder3/index.html#/login,而是跳转到https://domainname#/login

查看pushState的MDN文档,找到问题:

The new URL can be any URL in the same origin as the current URL. In contrast, setting window.location keeps you at the same document only if you modify only the hash.

API文档清晰的说明了pushState中的URL只会保留同一个origin,如果想保留保留整个文档而只改变hash,需要使用window.location。由于项目用的是hash路由,所以这里应该改成:

1
2
3
4
5
6
if (resStatus === TIMEOUT) {
// 跳转到login页面
window.location.href = '/#/login';
// 可省略
window.location.reload();
}

虽然window.location返回的是一个只读对象,但仍可给其赋值,从而导航到另一个页面。