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

如何在Next.js新App Router中实现ProgressBar?

适配Next.js App Router的进度条实现方案

1. 手动封装客户端组件监听路由事件

App Router要求交互性组件必须标记为客户端组件,直接基于路由事件手动实现进度条逻辑,完全可控:

'use client';

import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';

export default function CustomProgressBar() {
  const [progress, setProgress] = useState(0);
  const [isVisible, setIsVisible] = useState(false);
  const router = useRouter();

  useEffect(() => {
    let progressInterval: NodeJS.Timeout;

    const startProgress = () => {
      setIsVisible(true);
      setProgress(0);
      progressInterval = setInterval(() => {
        setProgress(prev => {
          if (prev >= 90) return prev;
          return prev + 10;
        });
      }, 150);
    };

    const completeProgress = () => {
      setProgress(100);
      setTimeout(() => setIsVisible(false), 300);
      clearInterval(progressInterval);
    };

    router.events.on('routeChangeStart', startProgress);
    router.events.on('routeChangeComplete', completeProgress);
    router.events.on('routeChangeError', completeProgress);

    return () => {
      router.events.off('routeChangeStart', startProgress);
      router.events.off('routeChangeComplete', completeProgress);
      router.events.off('routeChangeError', completeProgress);
      clearInterval(progressInterval);
    };
  }, [router]);

  if (!isVisible) return null;

  return (
    <div className="fixed top-0 left-0 right-0 z-50 h-1 bg-transparent">
      <div
        className="h-full bg-blue-600 transition-all duration-300 ease-out"
        style={{ width: `${progress}%` }}
      />
    </div>
  );
}

在根布局(app/layout.tsx)中引入该组件即可,它会自动监听所有路由切换事件。

2. 利用App Router内置的Loading组件

这是官方推荐的路由级加载方案,直接在目标路由段下创建loading.tsx文件,自定义成进度条样式:

'use client';

export default function Loading() {
  return (
    <div className="fixed top-0 left-0 right-0 z-50 h-1">
      <div className="h-full bg-green-500 animate-progress"></div>
    </div>
  );
}

在全局CSS(app/globals.css)中添加动画逻辑:

@keyframes progress {
  0% { width: 0%; }
  50% { width: 70%; }
  100% { width: 100%; }
}

.animate-progress {
  width: 100%;
  animation: progress 1.2s ease-in-out infinite;
}

该组件会在当前路由段的页面加载时自动显示,无需额外监听路由事件。

3. 封装现有NPM库适配App Router

如果偏好某个第三方进度条库(比如react-topbar-progress-indicator),可以用客户端组件包装它,手动关联App Router的路由事件:

'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import ProgressBar from 'react-topbar-progress-indicator';

ProgressBar.config({
  barColors: { 0: '#2563eb', 1.0: '#2563eb' },
  shadowBlur: 0,
});

export default function WrappedProgressBar() {
  const router = useRouter();

  useEffect(() => {
    const start = () => ProgressBar.start();
    const complete = () => ProgressBar.complete();

    router.events.on('routeChangeStart', start);
    router.events.on('routeChangeComplete', complete);
    router.events.on('routeChangeError', complete);

    return () => {
      router.events.off('routeChangeStart', start);
      router.events.off('routeChangeComplete', complete);
      router.events.off('routeChangeError', complete);
    };
  }, [router]);

  return null;
}

这样就能让原本适配Pages Router的库在App Router下正常工作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:22:52