这是我参与 8 月更文挑战的第 8 天,活动详情查看: 8月更文挑战html
众所周知, hash
和 history
在前端面试中是很常考的一道题目。在学习本文内容以前,周一对 hash
和 history
的认知可能就在 hash
的 url
里面多了个 #
,而 history
就不会。而后,我认知里还有一个是只有 history
才能作先后端分离,而 hash
跟先后端分离没有关系。然而,现实是……前端
对于前端路由来讲, hash
和 history
均可以用于先后端分离项目,且二者有各自的特色和各自的使用场景,在使用过程当中主要要了解当前项目所处的场景,以便于更好地判断使用哪种路由模式更佳。下面进入本文的讲解~😜vue
SPA,即单页面应用(Single Page Application)。所谓单页 Web
应用,就是只有一张 Web
页面的应用。单页应用程序 (SPA) 是加载单个 HTML
页面并在用户与应用程序交互时动态更新该页面的 Web
应用程序。浏览器一开始会加载必需的 HTML
、 CSS
和 JavaScript
,全部的操做都在这张页面上完成,都由 JavaScript
来控制。react
现现在,为了配合单页面 Web
应用快速发展的节奏,各种前端组件化技术栈层出不穷。近几年来,经过不断的版本迭代, vue
和 react
两大技术栈脱颖而出,成为当下最受欢迎的两大技术栈。nginx
对于现代开发的项目来讲,稍微复杂一点的 SPA
,都须要用到路由。而 vue-router
正是 vue
的路由标配,且 vue-router
有两种模式: hash
和 history
。git
下面就依据这两种模式来进行一一讲解。github
hash
模式是一种把前端路由的路径用井号 #
拼接在真实 url
后面的模式。当井号 #
后面的路径发生变化时,浏览器并不会从新发起请求,而是会触发 onhashchange
事件。面试
属性 | 含义 |
---|---|
location.protocal | 协议 |
location.hostname | 主机名 |
location.host | 主机 |
location.port | 端口号 |
location.patchname | 访问页面 |
location.search | 搜索内容 |
location.hash | 哈希值 |
下面用一个网址来演示以上属性:vue-router
//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
能够改变 url
,可是不会触发页面从新加载(hash的改变是记录在 window.history
中),即不会刷新页面。也就是说,全部页面的跳转都是在客户端进行操做。所以,这并不算是一次 http
请求,因此这种模式不利于 SEO
优化。hash
只能修改 #
后面的部分,因此只能跳转到与当前 url
同文档的 url
。
hash
经过 window.onhashchange
的方式,来监听 hash
的改变,借此实现无刷新跳转的功能。
hash
永远不会提交到 server
端(能够理解为只在前端自生自灭)。
history API
是 H5
提供的新特性,容许开发者直接更改前端路由,即更新浏览器 URL
地址而不从新发起请求。
咱们用一个例子来演示, hash
与 history
在浏览器下刷新时的区别。具体以下:
正常页面浏览
https://github.com/xxx 刷新页面
https://github.com/xxx/yyy 刷新页面
https://github.com/xxx/yyy/zzz 刷新页面
复制代码
改造H5 history模式
https://github.com/xxx 刷新页面
https://github.com/xxx/yyy 前端跳转,不刷新页面
https://github.com/xxx/yyy/zzz 前端跳转,不刷新页面
复制代码
下面阐述几种 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的调用 |
对于 history
来讲,主要有如下特色:
url
能够是与当前 url
同源的任意 url
,也能够是与当前 url
同样的地址,可是这样会致使的一个问题是,会把重复的这一次操做记录到栈当中。history.state
,添加任意类型的数据到记录中。title
属性,以便后续使用。pushState
、 replaceState
来实现无刷新跳转的功能。对于 history
来讲,确实解决了很多 hash
存在的问题,可是也带来了新的问题。具体以下:
history
模式时,在对当前的页面进行刷新时,此时浏览器会从新发起请求。若是 nginx
没有匹配获得当前的 url
,就会出现 404
的页面。hash
模式来讲, 它虽然看着是改变了 url
,但不会被包括在 http
请求中。因此,它算是被用来指导浏览器的动做,并不影响服务器端。所以,改变 hash
并无真正地改变 url
,因此页面路径仍是以前的路径, nginx
也就不会拦截。history
模式时,须要经过服务端来容许地址可访问,若是没有设置,就很容易致使出现 404
的局面。下面咱们再来介绍下在实际的项目中,如何对这二者进行选择。具体以下:
to B
的系统推荐用 hash
,相对简单且容易使用,且由于 hash
对 url
规范不敏感;to C
的系统,能够考虑选择 H5 history
,可是需要服务端支持;对于 hash
和 history
来说,要清楚二者的区别以及二者各自的使用场景,还有各自的使用特色和优缺点。以上文章只是对前端路由原理的浅谈,但愿对你们有帮助~
另下方第三个彩蛋放了一篇关于实现 vue-router
的文章,学有余力的小伙伴有须要自取o!
jarvis👉在SPA项目的路由中,注意hash与history的区别
vue-router官方文档👉vue-router的两种模式
值得一看👉从使用到本身实现简单Vue Router看这个就好了
- 关注公众号星期一研究室,第一时间关注优质文章,更多精选专栏待你解锁~
- 若是这篇文章对你有用,记得留个脚印jio再走哦~
- 以上就是本文的所有内容!咱们下期见!👋👋👋