单页应用(SPA)采用前端路由成为当前主流,通过改变 URL,在不重新请求页面的情况下,更新视图。目前,主要有两种实现方式:

1.hash:利用 URL 中的hash(# 符号)

# 代表网页中的一个位置,其右面的字符,就是该位置的标识符。比如:

    http://www.example.com/index.html#print

就代表网页index.html的print位置。浏览器读取这个 URL 后,会自动将print位置滚动至可视区域。

为网页位置指定标识符的方法有两种:

一、使用锚点,比如<a name="print"></a>

二、使用id属性,比如<div id="print" >

# 本身及其右边字符称之为hash,可通过window.location.hash属性读取,具有如下特点:

# 是用来指导浏览器动作的,对服务器端完全无用。所以,http请求中不包括 #

改变hash,浏览器只会滚动到相应位置,不会重新加载网页

可以为hash的改变添加监听事件:

    window.addEventListener("hashchange", funcRef, false)

每一次改变hash,都会在浏览器的访问历史中增加一个记录

利用hash的以上特点,就可以实现前端路由“更新视图但不重新请求页面”的功能了

 

2.history:利用HTML5 History Interface中新增的方法

History Interface是浏览器历史记录栈提供的接口,通过back(), forward(), go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。从HTML5开始,History Interface提供了两个新的方法:pushState() 和 replaceState(),使得我们可以对浏览器历史记录栈进行修改:

    window.history.pushState(stateObject, title, URL)
    window.history.replaceState(stateObject, title, URL)

这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前 URL 改变了,但浏览器不会立即发送请求(the browser won't attempt to load this URL after a call to pushState()),这就为单页应用前端路由“更新视图但不重新请求页面”提供了基础

 

两种模式比较

在一般场景中,hash模式与history模式是差不多的,但几乎所有的文章都推荐使用history模式,理由竟然是:"#" 符号太丑

history与hash相比,存在很多优势(省略百字,见下文链接)

但是,history存在一个问题

对于单页应用来讲,理想的使用场景是仅在进入应用时加载index.html,后续操作通过ajax来完成,不会根据 URL 重新请求页面,但是难免遇到特殊情况,比如用户直接在地址栏中输入并回车浏览器刷新或者重启

hash模式仅改变hash部分的内容,而hash部分是不会包含在HTTP请求中的:

    http://oursite.com/#/user/id   // 如重新请求只会发送http://oursite.com/

所以在hash模式下,当 URL 改变时,页面不会重新加载

而在history模式下,URL 就是正常的 URL(建议:前端路由 URL 和后端保持一致

    http://oursite.com/user/id

在此情况下重新(刷新F5)向后端发送请求,如后端没有配置对应/user/id的路由处理,则会返回404错误。

官方推荐的解决办法是在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

如果这么做,服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后再给出一个 404 页面。如果你使用 Node.js 服务器,你可以用服务端路由匹配到来的 URL,并在没有匹配到路由的时候返回 404,以实现回退。

vue官网提供了很多后端配置的例子:https://router.vuejs.org/zh/guide/essentials/history-mode.html#后端配置例子

我当前项目使用 spring 框架,配置也很简单,只需在 web.xml 下添加 error-page 标签

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/404.jsp</location>
    </error-page>

特别注意:404.jsp 页面大小 > 1024b

 

参考

从 vue-router 看前端路由的两种实现:https://zhuanlan.zhihu.com/p/27588422 

vue中mode hash 和 history的区别:https://blog.csdn.net/lyn1772671980/article/details/80804419

url中#的作用:https://blog.csdn.net/luka2008/article/details/38753269

解决vue router 使用 history 模式刷新后404问题:https://www.jb51.net/article/119075.htm

web.xml 中 error-page 的正确用法:http://www.cnblogs.com/sharpest/p/6108652.html

vue-router路由使用history模式时,后端如何配置:https://blog.csdn.net/wenmin1987/article/details/81069604

Logo

前往低代码交流专区

更多推荐