如何在Next.js + TypeScript中实现页面关闭确认弹窗
在Next.js + TypeScript中实现页面关闭确认弹窗
核心思路
Next.js存在服务端渲染阶段,window对象仅在客户端可用,因此必须通过useEffect在客户端组件中绑定页面关闭事件,同时要在组件卸载时清理事件监听,避免内存泄漏。
基础实现(App Router/Page Router通用)
如果是App Router,需要在组件顶部添加'use client'声明标记为客户端组件;Page Router无需额外声明,组件默认在客户端执行。
'use client'; // App Router 必须添加 import { useEffect } from 'react'; export default function EditPage() { useEffect(() => { // 绑定页面关闭/刷新事件 const handleBeforeUnload = (e: BeforeUnloadEvent) => { // 浏览器会忽略自定义文案,仅显示默认提示(不同浏览器文案不同) e.preventDefault(); // 必须返回一个值才能触发弹窗(部分浏览器要求) e.returnValue = ''; return ''; }; window.addEventListener('beforeunload', handleBeforeUnload); // 组件卸载时移除监听 return () => { window.removeEventListener('beforeunload', handleBeforeUnload); }; }, []); return ( <div> {/* 页面内容 */} </div> ); }
带状态控制的实现(仅当有未保存修改时弹窗)
避免用户无操作时也触发弹窗,可通过状态判断是否需要启用监听:
'use client'; import { useEffect, useState } from 'react'; export default function EditPage() { const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); // 监听输入变化,标记是否有未保存内容 const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { setHasUnsavedChanges(true); }; useEffect(() => { if (!hasUnsavedChanges) return; const handleBeforeUnload = (e: BeforeUnloadEvent) => { e.preventDefault(); e.returnValue = ''; return ''; }; window.addEventListener('beforeunload', handleBeforeUnload); return () => { window.removeEventListener('beforeunload', handleBeforeUnload); }; }, [hasUnsavedChanges]); // 保存后重置状态 const handleSave = () => { // 执行保存逻辑 setHasUnsavedChanges(false); }; return ( <div> <input type="text" onChange={handleInputChange} /> <button onClick={handleSave}>保存</button> </div> ); }
注意事项
- 自定义文案限制:现代浏览器(Chrome、Firefox等)会忽略
returnValue的自定义内容,仅显示浏览器默认的关闭确认文案,无法自定义。 - 内部路由跳转处理:
onbeforeunload仅触发于页面刷新、关闭或跳转到外部网站。如果需要在Next.js内部路由跳转时也弹出确认,需额外监听路由变化(比如使用useRouter的beforePopState方法)。
内容的提问来源于stack exchange,提问作者Skj0nes
相关产品推荐
相关产品推荐

