Next.js 13/14 App目录下如何在路由切换时显示顶部加载条?
在Next.js 13/14中实现页面切换顶部加载条(兼容Link与router.push)
方案一:App Router内置加载状态(基础页面骨架屏)
如果只需要页面级的加载占位提示,Next.js App Router自带loading.tsx功能:在对应路由目录下创建loading.tsx文件,就能在页面加载时显示骨架屏或自定义加载动画。但这种方式不是顶部进度条,适合需要页面级占位的场景。
方案二:自定义顶部加载条(推荐,适配所有跳转方式)
要实现顶部进度条且兼容Link组件和router.push(),可以通过监听路由全局事件实现,步骤如下:
1. 创建全局LoadingBar组件
在app/components目录下新建LoadingBar.tsx:
'use client'; import { useEffect, useState } from 'react'; import { useRouter, usePathname } from 'next/navigation'; export default function LoadingBar() { const [isLoading, setIsLoading] = useState(false); const router = useRouter(); const pathname = usePathname(); useEffect(() => { // 定义加载状态切换函数 const startLoading = () => setIsLoading(true); const stopLoading = () => setIsLoading(false); // 监听路由核心事件 router.events.on('routeChangeStart', startLoading); router.events.on('routeChangeComplete', stopLoading); router.events.on('routeChangeError', stopLoading); // 组件卸载时清理监听事件 return () => { router.events.off('routeChangeStart', startLoading); router.events.off('routeChangeComplete', stopLoading); router.events.off('routeChangeError', stopLoading); }; }, [router]); // 监听路径变化,覆盖边缘场景 useEffect(() => { setIsLoading(true); // 防止瞬间跳转时加载条无显示 const timer = setTimeout(() => setIsLoading(false), 300); return () => clearTimeout(timer); }, [pathname]); return ( <div className={`fixed top-0 left-0 right-0 h-1 bg-blue-500 z-50 transition-all duration-300 ease-in-out ${ isLoading ? 'w-full' : 'w-0' }`} /> ); }
2. 在根布局中全局引入
打开app/layout.tsx,将LoadingBar放在<body>最顶部,确保它能覆盖所有页面:
import LoadingBar from './components/LoadingBar'; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="zh-CN"> <body> <LoadingBar /> {children} </body> </html> ); }
3. 解决router.push()无效的核心逻辑
之前使用工具包仅Link组件生效,是因为工具包可能只监听了Link的点击事件,未覆盖路由系统的全局事件。这里通过router.events监听Next.js路由的三个核心事件:
routeChangeStart:无论点击Link还是调用router.push(),路由跳转开始时都会触发routeChangeComplete:路由跳转成功完成时触发routeChangeError:路由跳转失败(如404、网络错误)时触发
这三个事件能覆盖所有路由跳转场景,确保加载条同步响应。
额外优化建议
- 可修改加载条样式:比如换成渐变背景、调整动画时长,或添加进度模拟(如从0%到80%,完成时直接跳到100%)
- Next.js 13.4+支持
useRouter的isPending状态,可结合该状态实现更精细的进度控制 - 可根据不同路由路径动态调整加载条颜色,适配页面风格
内容的提问来源于stack exchange,提问作者Nested Gateway
相关产品推荐
相关产品推荐

