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

Next.js 13 App Router:提前检测导航事件并阻止导航

Next.js 13 App Router:提前感知并阻止导航

一、处理浏览器级导航(刷新、关闭标签页)

使用原生beforeunload事件,能在用户触发浏览器级导航前触发,通过弹出确认提示阻止导航:

'use client';

import { useEffect } from 'react';

export default function NavGuard() {
  useEffect(() => {
    const handleBeforeUnload = (e: BeforeUnloadEvent) => {
      e.preventDefault();
      e.returnValue = '';
      return '';
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, []);

  return null;
}

将这个组件放入根布局(app/layout.tsx),即可全局生效。

二、处理应用内导航(Next.js Link、router.push/replace)

App Router无内置导航前拦截事件,需通过自定义封装实现:

1. 拦截版自定义Link组件

封装Next.js原生Link,点击时先执行确认逻辑,用户同意后再导航:

'use client';

import Link from 'next/link';
import { useRouter } from 'next/navigation';

type InterceptedLinkProps = React.ComponentProps<typeof Link> & {
  shouldBlock?: () => boolean;
  confirmMessage?: string;
};

export function InterceptedLink({
  shouldBlock = () => false,
  confirmMessage = '你确定要离开当前页面吗?',
  ...props
}: InterceptedLinkProps) {
  const router = useRouter();

  const handleClick = (e: React.MouseEvent) => {
    if (shouldBlock()) {
      e.preventDefault();
      if (window.confirm(confirmMessage)) {
        router.push(props.href as string);
      }
    }
  };

  return <Link {...props} onClick={handleClick} />;
}

使用时替换原生Link,传入shouldBlock函数判断是否需要拦截。

2. 包装useRouter导航方法

对router.push/router.replace进行包装,添加拦截逻辑:

'use client';

import { useRouter as useNextRouter } from 'next/navigation';

export function useRouter() {
  const router = useNextRouter();

  const push = (href: string) => {
    if (window.confirm('你确定要离开当前页面吗?')) {
      router.push(href);
    }
  };

  const replace = (href: string) => {
    if (window.confirm('你确定要离开当前页面吗?')) {
      router.replace(href);
    }
  };

  return { ...router, push, replace };
}

后续在组件中使用这个自定义useRouter替代原生方法即可。

三、注意事项

  • 所有方案均需在客户端组件中实现(添加'use client'指令),依赖浏览器API和客户端路由逻辑。
  • beforeunload的自定义提示文本在部分现代浏览器中会被替换为系统默认内容,无法完全自定义。
  • 可根据页面状态(如表单未提交)修改shouldBlock或包装方法中的判断逻辑,实现动态拦截。

内容的提问来源于stack exchange,提问作者skellertor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:32:47