Next.js中浏览器返回按钮不触发离开确认弹窗问题
Next.js中浏览器返回按钮不触发离开确认弹窗的解决方案
问题分析
你当前通过beforeunload事件实现的离开确认逻辑,仅在页面刷新、浏览器关闭这类页面卸载场景下生效。但Next.js的客户端路由(包括浏览器返回按钮触发的导航)属于SPA内部的路由切换,不会触发页面卸载,因此beforeunload事件不会被触发,也就不会弹出确认弹窗。
解决方案
需要同时监听Next.js的客户端路由变化事件,结合beforeunload覆盖所有场景:
完整代码实现
import { useEffect } from 'react'; import { useRouter } from 'next/router'; export default function YourComponent() { const router = useRouter(); const latestGeneratedImages = []; // 替换为你的实际状态变量 useEffect(() => { // 处理页面卸载场景(刷新、关闭浏览器) const handleBeforeUnload = (event: BeforeUnloadEvent) => { if (latestGeneratedImages.length > 1) { event.preventDefault(); event.returnValue = true; } }; // 处理客户端路由切换场景(浏览器返回、页面内链接跳转) const handleRouteChangeStart = (url: string) => { if (latestGeneratedImages.length > 1) { const confirmLeave = window.confirm('你有未完成的内容,确定要离开吗?'); if (!confirmLeave) { // 终止路由跳转流程 router.events.emit('routeChangeError'); throw '路由跳转已取消'; } } }; window.addEventListener('beforeunload', handleBeforeUnload); router.events.on('routeChangeStart', handleRouteChangeStart); return () => { window.removeEventListener('beforeunload', handleBeforeUnload); router.events.off('routeChangeStart', handleRouteChangeStart); }; }, [latestGeneratedImages, router]); return <div>你的组件内容</div>; }
关键说明
routeChangeStart:Next.js路由开始变化时触发的事件,通过它可以拦截所有客户端路由跳转行为,包括浏览器返回按钮触发的导航。- 手动确认弹窗:
beforeunload的弹窗是浏览器原生样式,客户端路由切换场景需要手动调用window.confirm实现一致的确认逻辑。 - 终止路由跳转:当用户选择不离开时,通过
router.events.emit('routeChangeError')并抛出错误,来中断Next.js的路由切换流程。
注意事项
- 务必将
router加入依赖数组,避免因路由实例更新导致监听失效。 - 弹窗提示语尽量明确,告知用户离开可能带来的影响(比如未保存内容丢失)。
内容的提问来源于stack exchange,提问作者Farhan
相关产品推荐
相关产品推荐

