可通过封装 useblockback hook 实现轻量可控的返回拦截:统一管理 history、sessionstorage 缓存与用户意图,提供 block/unblock 方法及 onblocked 回调,支持脏检查、多步骤上下文识别与 ui 解耦。

不能靠 Hooks 单独“拦截返回”,但能用 Hooks 封装一套轻量、可复用、贴合业务的返回控制逻辑。核心是把 history 状态管理、sessionStorage 上下文缓存 和 用户意图判断 三者收拢进一个 Hook,让表单页调用时只需关心“要不要拦”和“拦了怎么办”。
封装 useBlockBack:统一注册与响应逻辑
这个 Hook 负责监听 popstate、读取 sessionStorage 中的标记,并提供主动设置拦截状态的能力。它不弹窗、不跳转,只暴露可控的开关和回调。
- 初始化时自动注册
window.addEventListener('popstate', ...) - 提供
block()方法:写入sessionStorage.setItem('blockBack', 'true')并调用history.pushState()覆盖当前历史项(视觉上“卡住”) - 提供
unblock()方法:清除标记,允许下次后退自然生效 - 触发拦截时,只调用传入的
onBlocked回调(例如弹 confirm、跳中转页、恢复草稿),不强制 UI
配合表单状态:在离开前自动标记 + 缓存数据
对复杂表单而言,“是否要拦”往往取决于“有没有未保存的修改”。Hook 可结合表单脏检查与数据快照,实现智能拦截。
- 使用
useEffect监听表单字段变化,设isDirty = true - 在路由跳转前(如点击「下一步」或
history.push前),调用block()并同步保存当前字段值:sessionStorage.setItem('formStep2Data', JSON.stringify(values)) - 返回触发 popstate 后,若检测到
blockBack === 'true',先调onBlocked,用户确认后可自动填充缓存数据,无需重新输入
支持多步骤流程:用 session 标识上下文,避免误拦
向导类表单(如注册、下单)常需区分“真想后退”和“误点浏览器返回”。可在 sessionStorage 中记录路径上下文,让拦截更精准。
- 每步跳转前存标识:
sessionStorage.setItem('currentStep', 'step3'),同时存上一步:sessionStorage.setItem('prevStep', 'step2') - popstate 触发时,对比
event.state?.step或 sessionStorage 中的 step 值:若从 step3 返回 step2,且 step2 数据已完整,可自动unblock();若返回的是非流程页(如从 step3 点浏览器返回到首页),才真正触发拦截 - 关闭标签页不影响,但刷新后 sessionStorage 仍在,适合单会话内连续操作
与 UI 解耦:拦截动作交给业务组件决定
Hook 不内置 Modal 或 Alert,而是把决策权完全交给使用者。这样既适配 Ant Design、Element Plus,也兼容自研弹窗体系。
-
onBlocked回调接收两个参数:{ goBack: () => void, cancel: () => void } - 组件内可自由选择:弹
Modal.confirm、显示顶部横幅、跳转到「暂存页」、甚至静默恢复表单并滚动到变更字段 - 例如:
onBlocked={({ goBack }) => message.warn('有未保存内容,确定离开?', goBack)}










