hash
带#标志的路由,主要用于监听url中的hash变化来进行路由跳转
优势:兼容性更好
history
window.history.back() // 后退
window.histoty.forward() // 前进
window.history.go(-3) // 后退三个页面
history.pushState 用于在浏览历史中添加历史记录,并不触发跳转,接受三个参数
state:一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。不需要这个对象,可以填null
title:新页面的标题,但是一般忽略,填null
url:新网址,需与当前页面处于同一域。浏览器地址栏显示网址
history.replaceState的参数与pushState方法一样,区别是修改历史中的当前记录,非添加记录,同样不触发跳转
popState事件,当同一文档的浏览历史History对象改变时,触发popState事件
以上方法需要用户点击浏览器倒退或前进按钮,或使用JS调用back、forward、go等方法触发
应用场景:
通过 pushState 把页面的状态保存在 state 对象中,当页面的 url 再变回到这个 url 时,可以通过 event.state 取到这个 state 对象,从而可以对页面状态进行还原,如页面滚动条的位置、阅读进度、组件的开关等。
调用history.pushState() 比使用 hash 存在的优势:
- pushState 设置的 url 可以是同源下的任意 url ;而 hash 只能修改 # 后面的部分,因此只能设置当前 url 同文档的 url
- pushState 设置的新的 url 可以与当前 url 一样,这样也会把记录添加到栈中;hash 设置的新值不能与原来的一样,一样的值不会触发动作将记录添加到栈中
- pushState 通过 stateObject 参数可以将任何数据类型添加到记录中;hash 只能添加短字符串
- pushState 可以设置额外的 title 属性供后续使用
劣势:
- history 在刷新页面时,如果服务器中没有相应的响应或资源,就会出现404。因此,如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面
- hash 模式下,仅 # 之前的内容包含在 http 请求中,对后端来说,即使没有对路由做到全面覆盖,也不会报 404
参考资料:
掘金· 西芹儿:history与hash路由的区别
扩展:
基于History实现前端路由