能否在页面跳转前捕获history.back事件并校验IsDirty标识状态?
实现方案说明
这个需求实现成本很低,核心是调用浏览器或前端路由提供的跳转前钩子,在钩子回调中读取IsDirty标识即可,不需要额外做复杂的事件拦截。
通用场景适配方案
1. 多页应用/跨页面跳转场景
直接监听浏览器beforeunload事件,该事件会在页面卸载、跳转动作正式执行前触发,完全满足前置查询的要求:
window.addEventListener('beforeunload', (event) => { // 跳转前读取IsDirty状态 const isDirty = /* 替换为你实际的IsDirty取值逻辑 */ false if (isDirty) { // 可在此处添加自定义逻辑,比如二次确认、数据暂存等 event.preventDefault() // 兼容部分浏览器的拦截规则,需要显式设置returnValue event.returnValue = '你有未保存的修改,确定要离开当前页面吗?' return event.returnValue } })
2. 单页应用(SPA)内部路由跳转场景
单页应用的内部路由跳转不会触发beforeunload事件,需要用对应框架路由提供的前置守卫钩子实现:
Vue + Vue Router 示例
直接使用组件内置的路由离开钩子:
import { onBeforeRouteLeave } from 'vue-router' // 在页面组件内声明 onBeforeRouteLeave((to, from, next) => { const isDirty = /* 替换为你实际的IsDirty取值逻辑 */ false if (isDirty) { // 执行你的自定义逻辑,比如弹出确认框 const allowLeave = confirm('存在未保存的修改,是否确认离开?') next(allowLeave) // 传入true允许跳转,false阻止跳转 return } next() })
React + React Router 示例
使用官方提供的拦截钩子:
import { useBlocker, useBeforeUnload } from 'react-router-dom' function EditPage() { const isDirty = /* 替换为你实际的IsDirty取值逻辑 */ false // 拦截单页内部路由跳转 const blocker = useBlocker(() => isDirty) // 兼容跨页面跳转的拦截 useBeforeUnload((event) => { if (isDirty) { event.preventDefault() event.returnValue = '存在未保存的修改,是否确认离开?' } }) // 自定义拦截后的弹窗逻辑,用户确认后调用blocker.proceed()即可放行跳转 if (blocker.state === 'blocked') { // 此处放置你的弹窗代码 } }
注意事项
- 不要使用
popstate事件做跳转拦截,该事件触发时跳转动作已经进入执行队列,无法阻止,不满足前置查询的要求 - 新版Chrome、Safari等浏览器会屏蔽
beforeunload事件的自定义提示文案,只会显示浏览器默认的提示文本,不需要额外做文案适配 - 如果是监听页面内自定义的返回按钮,直接给按钮的点击事件加前置判断即可,在跳转代码执行前先读取IsDirty做逻辑处理
内容的提问来源于stack exchange,提问作者F L O W I I I
相关产品推荐
相关产品推荐

