Skip to content
☆´∀`☆
On this page

路由的 hash 和 history

什么是前端路由?

复杂的 SPA 页面需要用到路由。

SPA,即单页面应用(Single Page Application)。所谓单页 Web 应用,就是只有一张 Web 页面的应用。单页应用程序 (SPA) 是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的 Web 应用程序。浏览器一开始会加载必需的 HTML 、 CSS 和 JavaScript ,所有的操作都在这张页面上完成,都由 JavaScript 来控制。

网页 URL 组成

  • url 的属性
location
协议
主机名
主机
端口号
访问页面
搜索内容
哈希值
javascript
//http://127.0.0.1:8001/01-hash.html?a=100&b=20#/aaa/bbb
location.protocal; // 'http:'
localtion.hostname; // '127.0.0.1'
location.host; // '127.0.0.1:8001'
location.port; //8001
location.pathname; //'01-hash.html'
location.serach; // '?a=100&b=20'
location.hash; // '#/aaa/bbb'

Hash 模式

什么是 hash 模式?

hash 模式是一种把前端路由的路径用井号 # 拼接在真实 url 后面的模式。当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange 事件。

hash 本身是做页面定位的,滚动到页面指定 DOM 元素。hash 模式的路由改变了这种约定。

hash 传参基于 URL,肯定就不能传输复杂的数据。但是 history 可以将参数存储到某个位置,用来处理 hash 的传参问题。

hash 的特点

  • hash 变化会触发网页跳转,即浏览器的前进和后退。
  • hash 可以改变 url ,但是不会触发页面重新加载(hash 的改变是记录在 window.history 中),即不会刷新页面。也就是说,所有页面的跳转都是在客户端进行操作。因此,这并不算是一次 http 请求,所以这种模式不利于 SEO 优化。hash 只能修改 # 后面的部分,所以只能跳转到与当前 url 同文档的 url 。
  • hash 通过 window.onhashchange 的方式,来监听 hash 的改变,借此实现无刷新跳转的功能。
  • hash 永远不会提交到 server 端(可以理解为只在前端自生自灭)。

History 模式

history API 是 H5 提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL 地址而不重新发起请求

与 hash 的区别

javascript
https://github.com/xxx 刷新页面

https://github.com/xxx/yyy 刷新页面

https://github.com/xxx/yyy/zzz 刷新页面
https://github.com/xxx 刷新页面

https://github.com/xxx/yyy 前端跳转,不刷新页面

https://github.com/xxx/yyy/zzz 前端跳转,不刷新页面

History 的 Api

history.pushState(data, title [, url])

pushState 主要用于往历史记录堆栈顶部添加一条记录。各参数解析如下:

①data会在 onpopstate 事件触发时作为参数传递过去;

②title为页面标题,当前所有浏览器都会忽略此参数;

url为页面地址,可选,缺少时表示为当前页地址

history.replaceState(data, title [, url])

更改当前的历史记录,参数同上; 上面的 pushState 是添加,这个更改

history.state

用于存储以上方法的 data 数据,不同浏览器的读写权限不一样

window.onpopstate

在点击浏览器前进、后退以及调用 history.go,history.back,history.forward 的时候触发。

History 的特点

  • 新的 url 可以是与当前 url 同源的任意 url ,也可以是与当前 url 一样的地址,但是这样会导致的一个问题是,会把重复的这一次操作记录到栈当中。
  • 通过 history.state ,添加任意类型的数据到记录中。
  • 可以额外设置 title 属性,以便后续使用。
  • 通过 pushState 、 replaceState 来实现无刷新跳转的功能。

History 的问题

  • 使用 history 模式时,在对当前的页面进行刷新时,此时浏览器会重新发起请求。如果 nginx 没有匹配得到当前的 url ,就会出现 404 的页面。history 模式 URL 改变会对服务器发起请求,需要在服务层做异常 URL 的 catch。
  • 而对于 hash 模式来说, 它虽然看着是改变了 url ,但不会被包括在 http 请求中。所以,它算是被用来指导浏览器的动作,并不影响服务器端。因此,改变 hash 并没有真正地改变 url ,所以页面路径还是之前的路径, nginx 也就不会拦截。
  • 因此,在使用 history 模式时,需要通过服务端来允许地址可访问,如果没有设置,就很容易导致出现 404 的局面。

两者选择

  • to B 的系统推荐用 hash ,相对简单且容易使用,且因为 hash 对 url 规范不敏感;
  • to C 的系统,可以考虑选择 H5 history ,但是需要服务端支持
  • 能先用简单的,就别用复杂的,要考虑成本和收益
  • hash 兼容到 IE8.history 只到 IE10. 但如今移动时代,兼容 IE 可以不考虑。
  • 大多数 web 应用程序都应该使用 createWebHistory,但它要求正确配置服务器。你还可以使用 createWebHashHistory 的基于 hash 的历史记录,它不需要在服务器上进行任何配置,但是搜索引擎根本不会处理它,在 SEO 上表现很差。