Skip to content

参考:速查 / 对比 / 易错点

基于 WHATWG HTML(导航与会话历史)现行标准与各浏览器 Baseline 状态 · 核于 2026-07

速查

  • History 入口window.historyHistory 接口,仅主线程);Navigation 入口window.navigationNavigation 接口,每窗口一个)。
  • History 改址pushState(state, unused, url) 推新条目 / replaceState(...) 替换当前;unused(title)被忽略url 必须同源
  • History 移动back()=go(-1) / forward()=go(1) / go(n) / go(0) 刷新;越界静默无效。
  • History 属性state(当前 state)/ length(条目数,含当前)/ scrollRestoration"auto"/"manual")。
  • History 事件popstate仅前进后退触发,push/replace 不触发)、hashchange
  • Navigation 方法navigate(url, {state,info,history}) / reload({state,info}) / back() / forward() / traverseTo(key,{info})——都返回 {committed,finished} Promise
  • Navigation 读栈entries()(完整同源栈)/ currentEntry / canGoBack / canGoForward / updateCurrentEntry({state})
  • Navigation 事件navigate(可 intercept)/ navigatesuccess / navigateerror / currententrychange
  • intercept({handler, precommitHandler, focusReset, scroll}):handler 提交后换内容、precommitHandler 提交前取数/重定向。
  • NavigateEvent 属性canIntercept / hashChange / downloadRequest / formData / userInitiated / navigationType / destination / info / signal
  • navigationType"push" / "replace" / "reload" / "traverse"
  • NavigationHistoryEntrygetState() / url / key(slot 标识,可 traverseTo)/ id(实例标识)/ index / sameDocument / dispose 事件。
  • key vs id:key 认"位置/slot"(traverseTo 用)、id 认"这一次导航实例"(埋点/缓存键用)。
  • 两 API state 都走结构化克隆:函数/DOM 节点存不了;History 的 state 在 Firefox 约 16 MiB 上限。
  • Baseline:Navigation API 2026-01 Newly Available(Chrome/Edge/Firefox 147/Safari 26.2);History API 2015 起全绿。
  • 特性检测"navigation" in window → 用 Navigation;否则降级 History。
  • hash vs history 路由:hash(#/pathhashchange无需后端)/ history(真路径,pushState必须服务端 fallback 到 index.html)。
  • 头号坑清单popstate 不因 push/replace 触发、history 路由刷新 404(漏配 fallback)、state 存不下函数、traverseTo key 失效、拦截前忘查 canIntercept

一、History 接口速查

1.1 方法

方法签名说明
pushStatepushState(state, unused, url?)推新历史条目;不刷页;unused 被忽略;url 同源否则 SecurityError
replaceStatereplaceState(state, unused, url?)替换当前条目;参数同上
backback()后退一条(=go(-1));越界静默
forwardforward()前进一条(=go(1));越界静默
gogo(delta?)相对跳转;go(0)/go() 刷新当前页

1.2 属性

属性类型说明
stateany(只读)当前历史条目的 state;初始为 null
lengthnumber(只读)会话历史条目数(含当前页);新标签页首页为 1
scrollRestoration"auto" | "manual"历史导航的滚动恢复策略;默认 "auto"

1.3 事件(在 window 上)

事件触发时机关键属性
popstate前进/后退、back/forward/go——push/replace 不触发event.state
hashchangeURL 的 fragment(# 后)变化event.oldURL / event.newURL

二、Navigation 接口速查

2.1 方法(均返回 { committed, finished }

方法签名说明
navigatenavigate(url, options?)optionsstate(结构化克隆)、info(一次性)、history"auto"/"push"/"replace"
reloadreload(options?)optionsstateinfo
backback()后退;canGoBack 为假则拒绝
forwardforward()前进;canGoForward 为假则拒绝
traverseTotraverseTo(key, options?)跳到 key 指定条目;optionsinfo;key 不存在抛 InvalidStateError

2.2 属性与读栈

成员类型说明
currentEntryNavigationHistoryEntry当前条目
entries()方法 → 数组完整同源历史栈
canGoBack / canGoForwardboolean能否前进后退
updateCurrentEntryupdateCurrentEntry({ state })只改当前 state、不导航、不入栈
transitionNavigationTransition | null进行中的导航(navigationType/from/finished

2.3 committed vs finished

Promise兑现时机
committed可见 URL 已变、新 NavigationHistoryEntry 已建立
finishedintercept() 所有 handler 的 Promise 兑现(等价 navigatesuccess);失败则拒绝

三、navigate 事件与 intercept

3.1 NavigateEvent 属性

属性类型用途
canInterceptboolean能否拦截;falseintercept()SecurityError——拦前必查
hashChangeboolean是否纯 fragment 变化
downloadRequeststring | nullnull 为下载链接(文件名)
formDataFormData | nullnull 为表单提交
userInitiatedboolean是否用户手势触发
navigationTypestring"push"/"replace"/"reload"/"traverse"
destinationobject目标:url/getState()/index/sameDocument/key/id
infoanynavigate(url, { info }) 传入的一次性信息
signalAbortSignal导航被取消时 abort——透传给 fetch

3.2 intercept 选项

选项说明
handlerasync fn提交后运行,渲染新内容
precommitHandlerasync fn(controller)提交前运行,可取数/校验/重定向;cancelable 导航可用,否则 SecurityError
focusReset"after-transition"(默认)/ "manual"默认聚焦 autofocus 元素或 <body>
scroll"after-transition"(默认)/ "manual"默认 push/replace 滚到 fragment/顶部;traverse/reload 延迟到 handler 完成再恢复

precommitHandlercontrollerredirect(url, { state, history }) 提交前重定向;addHandler(cb) 追加提交后 handler。

3.3 Navigation 生命周期事件

事件时机能否拦截
navigate导航开始、提交前intercept()
currententrychange当前条目已切换后(或 updateCurrentEntry 后,navigationTypenull❌ 只读
navigatesuccess所有 handler 成功、finished 兑现
navigateerror有 handler 失败、finished 拒绝

四、NavigationHistoryEntry 字段

字段类型含义
getState()方法读该条目的结构化克隆 state(任意条目均可,非仅当前)
urlstring条目 URL
keystringslot 标识——认"位置",traverseTo(key) 用;前进后退不变
idstring实例标识——认"这一次导航",每次新 entry 换新;埋点/缓存键用
indexnumberentries() 中的位置
sameDocumentboolean是否同文档导航(SPA 内 vs 跨文档加载)
dispose(事件)event条目被移出历史栈时触发——回收其绑定资源

五、两套 API 对比

维度History APINavigation API
入口window.historywindow.navigation
出身 / 兼容2015 全绿2026-01 Baseline,需特性检测降级
改址方法pushState/replaceStatenavigate({ history })
只改 statereplaceState(s,"",href)updateCurrentEntry({ state })
监听导航popstate仅前进后退)+hashchangenavigate 事件(所有导航
拦截换内容全局 click+preventDefault+手动渲染intercept({ handler })
读当前 statehistory.statecurrentEntry.getState()
读完整历史栈不能entries()
改非当前 entry不能任意 entry.getState() 可读
回到某页go(-n) 数步数traverseTo(key) 直达
能否前进后退无法可靠预判canGoBack/canGoForward
异步生命周期committed/finished + navigatesuccess/error
竞态取消自己实现event.signal
滚动接管scrollRestorationintercept({ scroll }) 更精细
焦点/无障碍自己管默认 focusReset 代管
条目回收事件entry.dispose

六、浏览器支持矩阵

API / 能力Chrome/EdgeFirefoxSafari备注
History API(pushState/popstate/state✅ 全绿2015 起 Widely Available
history.scrollRestoration2020 起 Widely Available
Navigation APInavigate/entries/intercept/traverseTo14726.22026-01 Baseline Newly Available

判断口径:Navigation API 用 "navigation" in window 特性检测,未命中就走 History API。History API 的 scrollRestoration"scrollRestoration" in history 检测(老环境极少缺)。Baseline "Newly Available" 意味着最新版全支持,但用户设备上的老版本仍可能缺——生产务必保留 History 降级。

七、易错点清单

  • 以为 pushState 会触发 popstate:不会——push 后要换 UI 必须自己调渲染popstate 只管前进后退。
  • history 路由刷新 404:漏配服务端 fallback 到 index.html——开发服务器帮你做了、生产没配就露馅(Nginx try_files $uri $uri/ /index.html;)。
  • pushState 第二参当标题传:被浏览器忽略——改标题用 document.title
  • pushState 传跨源 URL:抛 SecurityError——只能同源。
  • 把大对象/类实例/函数塞进 state:结构化克隆存不了函数/DOM,类实例丢方法;Firefox state 约 16 MiB 上限——history 只放 id,真数据放外部存储
  • 首屏没 replaceState 灌初始 state:一路后退回首屏时 popstate 的 state 为 null,还原不了——进应用先 replaceState(initialState, "", location.href)
  • history.length 判断"能否后退"length 含前进方向、且读不到具体条目——Navigation 用 canGoBack
  • intercept() 前不查 canIntercept:跨源等导航上直接 interceptSecurityError——先 if (!event.canIntercept) return;
  • 忘了放行 hashChange/downloadRequest:把锚点跳转、下载链接也拦了——守卫里 return 放行。
  • 在不可取消导航上用 precommitHandlertraversecancelable === false,用 precommit 抛 SecurityError——那种场景逻辑放 handler
  • 鉴权在 handler 里再导航:地址栏会先闪一下受限 URL——用 precommitHandler + controller.redirect 提交前改道。
  • 异步 handler 不透传 signal:快速切页时旧 fetch 晚回覆盖新内容(竞态)——fetch(url, { signal: event.signal })
  • traverseTo(key) 不处理 key 失效:key 被清出栈后抛 InvalidStateError——先 entries().some(e => e.key === key) 校验或 try/catch 降级。
  • 用了框架路由还自己接管 navigate:与框架导航逻辑打架——要么全交框架,要么只在无框架场景用原生。
  • 混淆 keyid:回某页用 key(认位置)、埋点/缓存键用 id(认这一次)——用反了逻辑就错。
  • 误以为 navigate 事件能收到跨源/跨文档一切:只覆盖同源导航;跨源、部分特殊导航 canIntercept 为假——安全边界与 History 一致。

八、权威链接