如何在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
相关产品推荐
相关产品推荐

