前端两种路由实现和使用场景--Hash模式&&History模式
什么是路由
路由这个概念最先是后端出现的,简单来说路由就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能。
前端路由的诞生
前端路由的出现要从 ajax 开始,有了 Ajax 后,用户交互就不用每次都刷新页面,体验带来了极大的提升。随着技术的发展,简单的异步已经不能满足需求,所以异步的更高级体验出现了——SPA(单页应用)。
SPA 的出现大大提高了 WEB 应用的交互体验。在与用户的交互过程中,不再需要重新刷新页面,获取数据也是通过 Ajax 异步获取,页面显示变的更加流畅。
但由于 SPA 中用户的交互是通过 JS 改变 HTML 内容来实现的,页面本身的 url 并没有变化,这导致了两个问题:
- SPA 无法记住用户的操作记录,无论是刷新、前进还是后退,都无法展示用户真实的期望内容。
- SPA 中虽然由于业务的不同会有多种页面展示形式,但只有一个 url,对 SEO 不友好,不方便搜索引擎进行收录。
前端路由就是为了解决上述问题而出现的。
什么是前端路由
简单的说,就是在保证只有一个 HTML 页面,且与用户交互时不刷新和跳转页面的同时,为 SPA 中的每个视图展示形式匹配一个特殊的 url。在刷新、前进、后退和SEO时均通过这个特殊的 url 来实现。
为实现这一目标,我们需要做到以下二点:
- 改变 url 且不让浏览器像服务器发送请求。
- 可以监听到 url 的变化
接下来要介绍的 hash 模式和 history 模式,就是实现了上面的功能。
Hash模式
原理
- 早期的前端路由的实现就是基于location.hash来实现的,location.hash的值就是URL中#后面的内容 其实现原理就是监听#后面的内容来发起Ajax请求来进行局部更新,而不需要刷新整个页面。
- 使用hashchange事件来监听 URL 的变化,以下这几种情况改变 URL 都会触发 hashchange 事件:浏览器前进后退改变 URL、a标签改变 URL、window.location改变URL。
使用
1 |
|
优点
- 兼容低版本浏览器,Angular1.x和Vue默认使用的就是hash路由
- 只有#符号之前的内容才会包含在请求中被发送到后端,也就是说就算后端没有对路由全覆盖,但是不会返回404错误
hash值的改变,都会在浏览器的访问历史中增加一个记录,所以可以通过浏览器的回退、前进按钮控制hash的切换 会覆盖锚点定位元素的功能
缺点
- 不太美观,#后面传输的数据复杂的话会出现问题
History模式
原理
- history 提供了 pushState 和 replaceState 两个方法来记录路由状态,这两个方法改变 URL 不会引起页面刷新
- history 提供类似 hashchange 事件的 popstate 事件,但 popstate 事件有些不同:通过浏览器前进后退改变 URL 时会触发 popstate 事件,通过pushState/replaceState或a标签改变 URL 不会触发 popstate 事件。好在我们可以拦截 pushState/replaceState的调用和a标签的点击事件来检测 URL 变化,所以监听 URL 变化可以实现,只是没有 hashchange 那么方便。
- pushState(state, title, url) 和 replaceState(state, title, url)都可以接受三个相同的参数。
使用
1 |
|
优点
- 使用简单,比较美观
- pushState()设置新的URL可以是任意与当前URL同源的URL,而hash只能改变#后面的内容,因此只能设置与当前URL同文档的URL
- pushState()设置的URL与当前URL一模一样时也会被添加到历史记录栈中,而hash#后面的内容必须被修改才会被添加到新的记录栈中
- pushState()可以通过stateObject参数添加任意类型的数据到记录中,而hash只能添加短字符串
- pushState()可额外设置title属性供后续使用
缺点
- 前端的URL必须和向发送请求后端URL保持一致,否则会报404错误
- 由于History API的缘故,低版本浏览器有兼容行问题
两种不同使用场景
- 从上文可见,hash模式下url会带有#,当你希望url更优雅时,可以使用history模式。
- 当使用history模式时,需要注意在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
- 当需要兼容低版本的浏览器时,建议使用hash模式。
- 当需要添加任意类型数据到记录时,可以使用history模式。
参考文章
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!