hash
和 history
在前端面试中是很常考的一道题目,可能很多人对于history和hash的理解差异性就是,他们两者的url字段一个没有#号一个有#号,但是有没有想过为什么这样呢,有无#号又有什么差异呢,这篇文章谈一谈我对前端路由history和hash的理解。
hash
和 history
都可以用于前后端分离项目,且两者有各自的特点和各自的使用场景。
一、前端路由原理
1、SPA
SPA,即单页面应用(Single Page Application)。所谓单页 Web
应用,就是只有一张 Web
页面的应用,不会像很久以前,前端交互是在多个页面进行跳转,每个页面之间都是相对独立的存在,单页面应用就是在一个页面上去动态更改页面的渲染内容。单页应用程序 (SPA) 是加载单个 HTML
页面并在用户与应用程序交互时动态更新该页面的 Web
应用程序。浏览器一开始会加载必需的 HTML
、 CSS
和 JavaScript
,所有的操作都在这张页面上完成,都由 JavaScript
来控制。
现如今,为了配合单页面 Web
应用快速发展的节奏,各类前端组件化技术栈层出不穷。近几年来,通过不断的版本迭代, vue
和 react
两大技术栈脱颖而出,成为当下最受欢迎的两大技术栈。
2、什么时候需要路由
国内现在基本使用的框架大部分都是Vue,vue传承的就是单页面应用开发形式。而 vue-router
正是 vue
的路由标配,且 vue-router
有两种模式: hash
和 history
。
下面就依据这两种模式来进行一一讲解。
二、Hash模式
1、定义
hash
模式是一种把前端路由的路径用井号 #
拼接在真实 url
后面的模式。当井号 #
后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange
事件。
比如:http://127.0.0.1:8001/01-hash.html?a=100&b=20#/aaa/bbb
2、hash的特点
-
hash变化会触发网页跳转,即浏览器的前进和后退。
-
hash
可以改变url
,但是不会触发页面重新加载(hash的改变是记录在window.history
中),即不会刷新页面。也就是说,所有页面的跳转都是在客户端进行操作。因此,这并不算是一次http
请求,所以这种模式不利于SEO
优化。hash
只能修改#
后面的部分,所以只能跳转到与当前url
同文档的url
。 -
hash
通过window.onhashchange
的方式,来监听hash
的改变,借此实现无刷新跳转的功能。 -
hash
永远不会提交到server
端(可以理解为只在前端自生自灭)。
三、History模式
1、定义
history API
是 H5
提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL
地址而不重新发起请求。
2、history的API
下面阐述几种 HTML5
新增的 history API
。具体如下表:
API | 定义 |
---|---|
history.pushState(data, title [, url]) | pushState主要用于往历史记录堆栈顶部添加一条记录。各参数解析如下:①data会在onpopstate事件触发时作为参数传递过去;②title为页面标题,当前所有浏览器都会忽略此参数;③url为页面地址,可选,缺少时表示为当前页地址 |
history.replaceState(data, title [, url]) | 更改当前的历史记录,参数同上; 上面的pushState是添加,这个更改 |
history.state | 用于存储以上方法的data数据,不同浏览器的读写权限不一样 |
window.onpopstate | 响应pushState或者replaceState的调用 |
3、history的特点
对于 history
来说,主要有以下特点:
- 新的
url
可以是与当前url
同源的任意url
,也可以是与当前url
一样的地址,但是这样会导致的一个问题是,会把重复的这一次操作记录到栈当中。 - 通过
history.state
,添加任意类型的数据到记录中。 - 可以额外设置
title
属性,以便后续使用。 - 通过
pushState
、replaceState
来实现无刷新跳转的功能。
4、存在问题
对于 history
来说,确实解决了不少 hash
存在的问题,但是也带来了新的问题。具体如下:
- 使用
history
模式时,在对当前的页面进行刷新时,此时浏览器会重新发起请求。如果nginx
没有匹配得到当前的url
,就会出现404
的页面。 - 而对于
hash
模式来说, 它虽然看着是改变了url
,但不会被包括在http
请求中。所以,它算是被用来指导浏览器的动作,并不影响服务器端。因此,改变hash
并没有真正地改变url
,所以页面路径还是之前的路径,nginx
也就不会拦截。 - 因此,在使用
history
模式时,需要通过服务端来允许地址可访问,如果没有设置,就很容易导致出现404
的局面。