路由有两种模式: hash 和 history
1 hash 哈希 --#开头
通常用于页面内导航 或者锚点
当哈希变化页面不会重新加载 ,而是触发hashChange事件
2 history
history.pushState() history.replaceState() history.back() 通过pushState、replaceState实现无刷新跳转的功能 ,上述方法添加 替换 或者移动历史记录 并不会导致页面实际刷新 当历史记录发生变化 浏览器不会重新加载页面 但可以通过popState捕获变化并做出响应
umi中封装了history
注意:
3.两者选择
在实际的项目中,如何选择:
-
to B的系统推荐用hash,相对简单且容易使用,且因为hash对url规范不敏感; -
to C的系统,可以考虑选择H5 history,但是需要服务端支持; -
能先用简单的,就别用复杂的,要考虑成本和收益。
4. 生产环境存在的问题
因为 history 模式的时候路径会随着 http 请求发送给服务器,项目打包部署时,需要后端配置 nginx,当应用通过 vue-router 跳转到某个页面后,因为此时是前端路由控制页面跳转,虽然url改变,但是页面只是内容改变,并没有重新请求,所以这套流程没有任何问题。但是,如果在当前的页面刷新一下,此时会重新发起请求,如果 nginx 没有匹配到当前url,就会出现404的页面。
那为什么hash模式不会出现这个问题呢? hash 虽然可以改变URL,但不会被包括在 HTTP 请求中。它被用来指导浏览器动作,并不影响服务器端,因此,改变 hash 并没有改变URL,所以页面路径还是之前的路径,nginx 不会拦截。 因此,切记在使用 history 模式时,需要服务端允许地址可访问,否则就会出现404的尴尬场景。
另外一种表达是 - 使用
history模式时,在对当前的页面进行刷新时,此时浏览器会重新发起请求。如果nginx没有匹配得到当前的url,就会出现404的页面。
而对于
hash模式来说, 它虽然看着是改变了url,但不会被包括在http请求中。所以,它算是被用来指导浏览器的动作,并不影响服务器端。因此,改变hash并没有真正地改变url,所以页面路径还是之前的路径,nginx也就不会拦截。因此,在使用
history模式时,需要通过服务端来允许地址可访问,如果没有设置,就很容易导致出现404的局面。
那为什么开发环境时就不会出现404呢?
因为在 vue-cli 中 webpack 帮我们做了处理
解决问题
生产环境 刷新 404 的解决办法可以在 nginx 做代理转发,在 nginx 中配置按顺序检查参数中的资源是否存在,如果都没有找到,让 nginx 内部重定向到项目首页。