【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 集成路由跳转显式进度条的封装。

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

感谢观看!👏

相关推荐
赵得C12 分钟前
【前端技巧】Element Table 列标题如何优雅添加 Tooltip 提示?
前端·elementui·vue·table组件
wow_DG15 分钟前
【Vue2 ✨】Vue2 入门之旅 · 进阶篇(一):响应式原理
前端·javascript·vue.js
weixin_4569042719 分钟前
UserManagement.vue和Profile.vue详细解释
前端·javascript·vue.js
资深前端之路22 分钟前
react 面试题 react 有什么特点?
前端·react.js·面试·前端框架
aaaweiaaaaaa23 分钟前
HTML和CSS学习
前端·css·学习·html
秋秋小事29 分钟前
React Hooks useContext
前端·javascript·react.js
Jinuss31 分钟前
Vue3源码reactivity响应式篇之reactive响应式对象的track与trigger
前端·vue3
striver_#32 分钟前
百度前端社招面经二
前端
xcnn_33 分钟前
前端入门——案例一:登录界面设计(html+css+js)
前端·css·html
ST.J33 分钟前
前端笔记2025
前端·javascript·css·vue.js·笔记