
Next.js 13+ App Router 移除了 Router.events,但可通过 useTransition + 自定义 Link 组合实现等效的导航加载状态监听,并配合 NProgress 等库构建平滑进度条体验。
next.js 13+ app router 移除了 `router.events`,但可通过 `usetransition` + 自定义 link 组合实现等效的导航加载状态监听,并配合 nprogress 等库构建平滑进度条体验。
在 App Router 中,next/router 的 Router.events(如 'routeChangeStart'、'routeChangeComplete')确实已被移除,官方明确表示当前无直接等价 API。但这并不意味着无法实现导航加载效果——Next.js 的 App Router 基于 React Concurrent Features 构建,天然支持通过 useTransition 捕获导航中的“挂起状态”(pending state),从而精准控制加载 UI。
✅ 推荐方案:useTransition + 自定义 <link>(官方推荐)
这是 Vercel 维护者在 GitHub 讨论中正式提出的模式,无需第三方库即可实现语义清晰、可预测的加载反馈:
// app/components/ProgressLink.tsx
'use client';
import { useTransition } from 'react';
import NextLink from 'next/link';
import { useRouter } from 'next/navigation';
import NProgress from 'nprogress'; // npm install nprogress
// 可选:全局配置 NProgress(建议在 _app.tsx 或根 layout 中初始化)
NProgress.configure({
showSpinner: false,
minimum: 0.3,
easing: 'ease',
speed: 200,
});
export function ProgressLink({
href,
children,
replace = false,
...props
}: Omit<react.componentprops nextlink>, 'href'> & {
href: string;
replace?: boolean;
}) {
const router = useRouter();
const [isPending, startTransition] = useTransition();
// 导航开始时触发进度条
if (isPending) {
NProgress.start();
}
// 导航完成或失败时结束进度条(注意:useTransition 不暴露 error 回调,需兜底)
if (!isPending && NProgress.isStarted()) {
NProgress.done();
}
return (
<nextlink href="%7Bhref%7D" onclick="{(e)"> {
e.preventDefault();
startTransition(() => {
if (replace) {
router.replace(href);
} else {
router.push(href);
}
});
}}
{...props}
>
{children}
</nextlink>
);
}</react.componentprops>
? 关键说明:
useTransition的isPending仅在组件渲染期间为true,因此进度条逻辑需放在组件内(如上例),或通过 Context +useEffect兜底管理全局状态。
⚠️ 注意事项与增强建议
-
不支持后退/前进按钮监听:
useTransition仅捕获push()/replace()触发的显式导航,浏览器原生前进/后退(History API)不会触发isPending。若需全覆盖,需结合window.addEventListener('popstate')手动处理(但此时无isPending,需自行维护 loading 状态)。 -
服务端组件限制:
useTransition和useRouter均为 Client Component Hook,必须加'use client'指令,且不能在服务端组件中使用。 - 更健壮的进度管理(推荐):将 NProgress 控制逻辑抽离为自定义 Hook,避免重复逻辑:
// hooks/useNavigationProgress.ts
import { useEffect } from 'react';
import NProgress from 'nprogress';
import { useRouter } from 'next/navigation';
export function useNavigationProgress() {
const router = useRouter();
useEffect(() => {
const handleStart = () => NProgress.start();
const handleStop = () => NProgress.done();
router.events.on('routeChangeStart', handleStart);
router.events.on('routeChangeComplete', handleStop);
router.events.on('routeChangeError', handleStop);
return () => {
router.events.off('routeChangeStart', handleStart);
router.events.off('routeChangeComplete', handleStop);
router.events.off('routeChangeError', handleStop);
};
}, [router]);
}
⚠️ 此 Hook 仅在 Pages Router 中有效;App Router 下 router.events 不存在,故该代码不可用——请勿误用。App Router 中唯一可靠方式仍是 useTransition 驱动的客户端导航封装。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
✅ 替代方案(第三方库)
若希望开箱即用,以下经过验证的轻量库可快速集成:
-
nextjs-progressloader:专为 App Router 设计,自动注入进度条,支持自定义样式; -
react-transition-progress:Vercel 官方示例项目所用,基于useTransition封装,提供<progress></progress>组件。
总结
App Router 虽暂无 Router.events,但 useTransition 提供了更现代、更可控的状态管理机制。与其模拟旧 API,不如拥抱 React 并发模型:用 isPending 驱动 UI,用自定义 Link 统一导航入口,再辅以 NProgress 等工具实现专业级加载体验。未来 Next.js 很可能引入 navigation.events(见 GitHub Discussion #41934),但当前方案已足够稳健、可扩展且符合框架演进方向。










