Skip to content

History

History API 用于读取和操作浏览器的会话历史记录。最常见的场景是前进、后退,以及单页应用里的地址切换但不整页刷新。

history 是什么

浏览器会为当前标签页维护一条历史记录栈,window.history 暴露的就是对这条记录的访问能力。

js
window.history
history

它常用于:

  • 调用浏览器后退和前进
  • 修改当前地址栏 URL
  • 在 SPA 中配合路由记录页面状态

常用属性

history.length

表示当前会话历史记录中的条目数量。

js
console.log(history.length)

history.state

返回当前历史条目关联的状态对象。如果当前条目没有通过 pushState()replaceState() 设置过状态,通常为 null

js
console.log(history.state)

history.scrollRestoration

用于控制浏览器在导航时是否自动恢复滚动位置。

js
history.scrollRestoration = 'auto'
history.scrollRestoration = 'manual'
  • auto:浏览器自动恢复滚动位置
  • manual:由应用自己控制滚动恢复

常用方法

back()

等价于浏览器后退按钮。

js
history.back()

forward()

等价于浏览器前进按钮。

js
history.forward()

go(delta)

按偏移量跳转历史记录:

js
history.go(-1) // 后退一页
history.go(1) // 前进一步
history.go(0) // 刷新当前页

pushState()

pushState(state, unused, url) 会新增一条历史记录,并可选地修改地址栏 URL,但不会触发整页刷新。

js
history.pushState({ tab: 'profile' }, '', '/account/profile')

这类写法通常用于:

  • 单页应用切换路由
  • Tab、筛选条件、分页状态进历史栈
  • 保持地址栏与页面状态同步

参数说明

  • state:与当前条目关联的状态对象
  • unused:历史遗留参数,通常传空字符串
  • url:新的地址,必须与当前页面同源

replaceState()

replaceState(state, unused, url) 会替换当前历史记录,而不是新增一条。

js
history.replaceState({ page: 2 }, '', '/list?page=2')

它适合:

  • 修正当前地址而不希望多出一条历史记录
  • 首次渲染后补写默认查询参数
  • 更新当前页面状态但不影响返回路径

popstate 事件

当用户点击前进/后退,或脚本调用 history.go() 导致当前条目变化时,通常会触发 popstate 事件。

js
window.addEventListener('popstate', (event) => {
  console.log(event.state)
})

要点是:

  • pushState()replaceState() 本身不会触发 popstate
  • 真正切换到其他历史条目时,才会触发该事件

和路由的关系

前端路由常见有两种模式:

  • 基于 history.pushState() 的 History 路由
  • 基于 location.hash 的 Hash 路由

History 模式的地址更自然,但服务端通常也要正确处理直达刷新,否则会出现 404。

使用建议

  • 需要无刷新修改地址时,优先使用 pushState()replaceState()
  • 想保留“返回上一步”路径时,用 pushState();只想覆盖当前状态时,用 replaceState()
  • state 适合保存轻量 UI 状态,不适合塞入过大对象。
  • 直接操作历史记录时,要同时考虑地址、页面内容和返回行为是否一致。

参考资料

基于 MIT 许可发布