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

Next.js 13.4 App目录下实现全局路由切换加载器方案咨询

在Next.js 13.4 App目录实现全局路由切换加载器的方案

在Next.js 13.4的App Router架构下,实现全局路由切换加载器可以通过以下几种原生或自定义方案解决,不需要依赖已移除的导航事件监听器:

方案一:利用useRouter的isPending状态(最简便的原生方案)

Next.js 13.4+的App Router中,next/navigation提供的useRouter钩子新增了isPending属性,会在路由切换(包括客户端导航和路由预加载)时自动切换为true,完成后恢复为false。你可以直接在根布局中基于这个状态渲染全局加载器。

示例代码:

// app/layout.tsx
import { useRouter } from 'next/navigation';
import './globals.css';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const router = useRouter();

  return (
    <html lang="en">
      <body>
        {/* 全局加载器 */}
        {router.isPending && (
          <div className="global-loader">
            <div className="loader-spinner"></div>
          </div>
        )}
        {children}
      </body>
    </html>
  );
}

对应的全局样式(globals.css):

.global-loader {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.loader-spinner {
  width: 48px;
  height: 48px;
  border: 5px solid #000;
  border-bottom-color: transparent;
  border-radius: 50%;
  animation: rotation 1s linear infinite;
}

@keyframes rotation {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

方案二:自定义拦截Link组件(补充边缘场景)

如果遇到isPending未覆盖的导航场景(比如某些自定义触发的路由跳转),可以封装一个自定义Link组件,手动管理加载状态,同时结合isPending保证一致性:

// components/CustomLink.tsx
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useState, useEffect } from 'react';

type CustomLinkProps = React.ComponentProps<typeof Link>;

export default function CustomLink({ children, ...props }: CustomLinkProps) {
  const router = useRouter();
  const [isNavigating, setIsNavigating] = useState(false);

  const handleClick = () => {
    setIsNavigating(true);
  };

  // 路由切换完成后重置状态
  useEffect(() => {
    if (!router.isPending) {
      setIsNavigating(false);
    }
  }, [router.isPending]);

  // 合并两种状态确保加载器覆盖所有导航场景
  const showLoader = isNavigating || router.isPending;

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

使用时直接替换原生Link为CustomLink即可,加载器仍复用根布局中的全局组件。

方案三:结合页面loading.tsx实现全局+局部加载

如果你的页面有单独的loading.tsx(页面级骨架屏),可以让全局加载器在路由切换初期显示,页面级加载组件接管后续状态,避免重复加载提示。只需要保证根布局的全局加载器在isPending为true时显示即可,页面的loading.tsx会自动在组件数据获取时渲染。

注意事项

  • 确保全局加载器的CSS使用fixed定位,避免被页面内容遮挡。
  • 对于服务端渲染的路由切换,isPending同样会生效,因为Next.js会在客户端导航开始时同步更新这个状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:13:36