You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:57:07