【Next.js】路由跳转显示进度条

本期已录制 B 站视频 👉 【Next.js】路由跳转显示进度条

哈喽,我是楷鹏。

先来看一个反面教材。

Dify.ai 中,当点击跳转页面之后,会有一段需要等待的时间,然后才会跳转页面。

然而,中间这段时间我并不知道是否跳转成功了,所以我会多点了几下,直到跳转。

这种体验很不好 👎

解决方案很简单,我们来看一下 GitHub 的跳转交互。

可以看到,GitHub 在跳转期间,会显示一个进度条,清晰地告诉用户------"我正在跳转,请稍等"。

那么在 Next.js 中,如何实现这个效果呢?

我们可以借助 BProgress 这个库来实现。

BProgress 是一个轻量级的进度条组件库,支持 Next.js 15+,同时也支持 Remix、Vue 等其他框架。

对于 BProgress 的使用,我做了一个 demo 项目 nextjs-progress-bar-demo,我们可以把这个项目先 clone 下来:

bash 复制代码
git clone git@github.com:wukaipeng-dev/nextjs-progress-bar-demo.git

然后进入项目目录:

bash 复制代码
cd nextjs-progress-bar-demo

先安装依赖:

bash 复制代码
npm install @bprogress/next

启动项目:

bash 复制代码
npm run dev

可以看到,这是一个简单的 Next.js 项目,包含三个页面:首页、登录页、注册页。

main 分支已经配置好了进度条,我们切换到分支 without-progress-bar-demo

bash 复制代码
git checkout without-progress-bar-demo

当前分支下,我们没有配置进度条,所以跳转页面时,不会显示进度条。

接下来我们在根布局 app/layout.tsx 中引入 ProgressProvider

tsx 复制代码
'use client';

import "./globals.css";
import { ProgressProvider } from '@bprogress/next/app';

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body>
        <ProgressProvider
          height="4px"
          color="#4c3aed"
          options={{ showSpinner: false }}
          shallowRouting
          >
          {children}
        </ProgressProvider>
      </body>
    </html>
  );
}

接下来,我们可以看一下,在首页和登录页、登录页和注册页之间跳转,都会显示一个进度条。

ProgressProvider 的参数如下:

  • height:进度条的高度
  • color:进度条的颜色
  • options:进度条的配置,这里 showSpinner 设置为 false,表示不显示一个动画的加载图标。
  • shallowRouting:是否启用浅层路由,如果开启的话,只改变路由的 query 参数,比如 ?page=1 变成 ?page=2,那么进度条不会重新加载。

但是,当我们登录成功之后,再点击跳转,却不会显示进度条。

这是因为,首页和登录页、登录页和注册页之间,是使用 <Link> 组件进行跳转的。

<Link> 组件实际会渲染成 <a>,BProgress 通过给所有 <a> 组件添加点击事件,来显示进度条。

我们可以看下在 DevTools → Elements → <a> → Event Listeners 中,是否添加了点击事件:

但是,当我们登录成功之后,则是使用 router.push 进行跳转的。

BProgress 不会给 router.push 添加点击事件,自然也不会显示进度条。

不用慌,BProgress 为我们提供了 useRouter 方法。

将 Next.js 的 useRouter 替换为 BProgress 提供的 useRouter

tsx 复制代码
// import { useRouter } from 'next/navigation';
import { useRouter } from '@bprogress/next/app';

然后,正常使用即可:

tsx 复制代码
const router = useRouter();

router.push('/');

这时,你可以看到,在登录成功之后,自动跳转首页时,进度条就能正常显示了。

但如果你的项目已经封装过了自己的 useRouter,那么你可以将封装过的 useRouter 作为参数 customRouter 传入,进行二次封装:

tsx 复制代码
import { useRouter } from '@bprogress/next/app';
import { useRouter as useNextIntlRouter } from '@/i18n/navigation';

export default function Home() {
  const router = useRouter({
    customRouter: useNextIntlRouter,
  });

  return (
    <button
      onClick={() =>
        router.push('/about', {
          startPosition: 0.3,
          locale: 'en',
        })
      }
    >
      Go to about page
    </button>
  );
}

最后,让我们回到 app/layout.tsx,这里我们引入了 ProgressProvider,但却把 app/layout 变成了一个客户端组件,我们来把 ProgressProvider 抽离到其他地方,仍然保持 app/layout 是一个服务端组件。

tsx 复制代码
// app/components/ProgressWrapper.tsx
'use client';

import { ProgressProvider } from '@bprogress/next/app';

interface ProgressWrapperProps {
  children: React.ReactNode;
}

export function ProgressWrapper({ children }: ProgressWrapperProps) {
  return (
    <ProgressProvider
      height="4px"
      color="#0000ff"
      options={{ showSpinner: false }}
      shallowRouting
    >
      {children}
    </ProgressProvider>
  );
}

app/layout.tsx 中,我们引入 ProgressWrapper

tsx 复制代码
import { ProgressWrapper } from './components/ProgressWrapper';

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body>
        <ProgressWrapper>
          {children}
        </ProgressWrapper>
      </body>
    </html>
  );
}

好的,不愧是你,完成了一个 Next.js 集成路由跳转显式进度条的封装。

以上就是本期的全部内容,希望对你有所帮助。

感谢观看!👏

相关推荐
Mintopia12 分钟前
Vite 发展现状与回顾:从“极致开发体验”到生态基础设施
前端
前端双越老师35 分钟前
前端面试常见的 10 个场景题
前端·面试·求职
孟祥_成都1 小时前
【全网最通俗!新手到AI全栈开发必读】 AI 是如何进化到大模型的
前端·人工智能·全栈
牛奶2 小时前
AI辅助开发的基础概念
前端·人工智能·ai编程
摸鱼的春哥2 小时前
Agent教程15:认识LangChain,Agent框架的王(上)
前端·javascript·后端
明月_清风3 小时前
自定义右键菜单:在项目里实现“选中文字即刻生成新提示”
前端·javascript
明月_清风3 小时前
告别后端转换:高质量批量导出实战
前端·javascript
刘发财7 小时前
弃用html2pdf.js,这个html转pdf方案能力是它的几十倍
前端·javascript·github
牛奶10 小时前
2026年大模型怎么选?前端人实用对比
前端·人工智能·ai编程
牛奶10 小时前
前端人为什么要学AI?
前端·人工智能·ai编程