本文摘自我的个人博客 ,未经允许请勿转载。
遇到问题
之前试着把手搓的个人博客部署到Github Pages上。部署过程不难,网页也如预期加载。然后我随手刷新了一下,发现除了首页以外,子路由都会报404。
我想大概是Vue Router的原因,事实也的确是这样。
浏览器刷新时,如果路径改变,就会按照路径发送资源请求。但此时的URL是Vue Router在History模式下设置的,直接按此请求肯定找不到资源,于是就返回404了。
解决问题
1. 寻找方案
我在网上查了下,找到了三种主流解决办法:
- 后端添加重定向
- 改用Hash路由
- 在index.html所在目录下直接添加一个内容与之相同的404.html
第一种方法想都不用想,Github(Gitee) Pages仅支持托管静态页面。
第二种方法会给URL增加井号,不咋美观。而且我的文章toc定位就是用便捷的锚点链接实现的,我不想为了改用Hash路由就重写个定位方式甚至直接放弃toc定位,所以也没采用。
第三种方法思路对了一半。该方法利用了Github(Gitee) Pages支持自定义404页面的功能,在404.html中渲染与原网页相同的内容以防止网页丢失。但该方法仅在普通页面里可行,在Vue项目里不适用。毕竟,不可能又在404.html里面挂载根组件吧?这也太蠢了。我们换个思路,其实只需要把404.html当作跳板,重定向回相应路由即可。
2. 实施过程
- 在public目录下新建404.html,并在head标签中添加了:
<script>
sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0; URL='/'">
- 在index.html中body标签上方添加了:
<script>
(function () {
const redir = sessionStorage.redirect;
delete sessionStorage.redirect;
if (redir && redir !== location.href) {
history.replaceState(null, null, redir);
}
})();
</script>
这样,跳转至404.html时会保存此时的地址,然后立即刷新并导航至根链接(即回到index.html),index.html在加载body前用保存的地址替换掉根链接,这样Vue Router就能据此正确地导航回来了。
涉及知识点
前端路由
前端路由有两种模式,Hash和History。
Hash:利用锚点定位原理,哈希值改变时触发hashChange事件并执行改变DOM的回调函数。这是前端Hash路由的基本原理。
- 优点:
- 兼容性佳
- 无需后端参与,
- 缺点:
- URL不美观
- 占用了锚点定位功能
History:利用H5中History API新增的pushState、replaceState方法,直接更改URL而不用重新请求。
- 优点:
- URL美观,符合规范
- 缺点:
- 兼容性不如Hash
- 基于此的SPA页面需要后端设置重定向