Next.js(React)应用点击链接无浏览器加载进度条问题如何解决
解决方案
你遇到的是Next.js客户端路由跳转的典型问题:Next.js内部跳转不会触发浏览器原生加载条,路由切换过程中页面无变化导致用户误解。不需要修改现有任何Link组件代码,通过监听全局路由事件控制加载状态展示即可,以下是两种常用实现方案:
方案1:全局顶部进度条(改造成本最低,行业通用)
- 安装依赖
npm install nprogress # 或 yarn add nprogress
- 在根组件
_app.jsx/_app.tsx中添加路由监听逻辑:
import { useEffect } from 'react'; import { useRouter } from 'next/router'; import NProgress from 'nprogress'; import 'nprogress/nprogress.css'; export default function App({ Component, pageProps }) { const router = useRouter(); useEffect(() => { // 路由开始切换时启动进度条 const handleRouteStart = () => NProgress.start(); // 路由切换完成/出错时关闭进度条 const handleRouteEnd = () => NProgress.done(); router.events.on('routeChangeStart', handleRouteStart); router.events.on('routeChangeComplete', handleRouteEnd); router.events.on('routeChangeError', handleRouteEnd); // 组件卸载时移除事件监听 return () => { router.events.off('routeChangeStart', handleRouteStart); router.events.off('routeChangeComplete', handleRouteEnd); router.events.off('routeChangeError', handleRouteEnd); }; }, [router.events]); return <Component {...pageProps} />; }
你可以通过覆盖nprogress的CSS自定义进度条的颜色、粗细、位置等样式。
方案2:自定义圆形加载动画(符合你需要的参考效果)
- 封装全局圆形加载组件:
// components/GlobalLoading.jsx export default function GlobalLoading({ visible }) { if (!visible) return null; return ( <div className="global-loading" /> ) }
- 在全局样式文件中添加加载动画样式:
.global-loading { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 99999; width: 40px; height: 40px; border: 4px solid #f0f0f0; border-top-color: #0070f3; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: translate(-50%, -50%) rotate(0deg); } 100% { transform: translate(-50%, -50%) rotate(360deg); } }
- 在根组件
_app.jsx/_app.tsx中引入并控制加载状态:
import { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; import GlobalLoading from '../components/GlobalLoading'; export default function App({ Component, pageProps }) { const router = useRouter(); const [loading, setLoading] = useState(false); useEffect(() => { const handleRouteStart = () => setLoading(true); const handleRouteEnd = () => setLoading(false); router.events.on('routeChangeStart', handleRouteStart); router.events.on('routeChangeComplete', handleRouteEnd); router.events.on('routeChangeError', handleRouteEnd); return () => { router.events.off('routeChangeStart', handleRouteStart); router.events.off('routeChangeComplete', handleRouteEnd); router.events.off('routeChangeError', handleRouteEnd); }; }, [router.events]); return ( <> <GlobalLoading visible={loading} /> <Component {...pageProps} /> </> ); }
注意事项
- 以上方案适配Next.js Pages Router版本,如果你使用的是Next.js 13+ App Router版本,只需将路由监听逻辑替换为
next/navigation提供的usePathname、useSearchParams等hook监听路径变化即可,核心逻辑一致。 - 如果有跳转外部站的链接,需要单独给a标签绑定点击事件触发加载状态。
内容的提问来源于stack exchange,提问作者taurOan
相关产品推荐
相关产品推荐

