You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中实现页面加载状态指示器的通用方案是什么?

Next.js页面跳转加载状态指示器实现方案

在Next.js中,页面跳转时如果加载耗时较长,缺乏状态提示会直接影响用户体验,下面是几种实用的落地方案:

1. Pages Router:利用Router事件全局监听

在Pages Router的_app.js中,通过监听Next.js Router的路由切换事件,统一控制加载状态的显示:

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import LoadingSpinner from '../components/LoadingSpinner';

function MyApp({ Component, pageProps }) {
  const [isLoading, setIsLoading] = useState(false);
  const router = useRouter();

  useEffect(() => {
    const handleStart = () => setIsLoading(true);
    const handleComplete = () => setIsLoading(false);
    const handleError = () => setIsLoading(false);

    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleComplete);
    router.events.on('routeChangeError', handleError);

    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleComplete);
      router.events.off('routeChangeError', handleError);
    };
  }, [router]);

  return (
    <>
      {isLoading && <LoadingSpinner />}
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

说明:这种方式可以覆盖所有路由跳转场景,适合需要统一加载提示的项目。LoadingSpinner是自定义的加载组件,比如居中的旋转图标或全屏遮罩。

2. App Router:使用内置的loading.js(Next.js 13+)

Next.js 13+的App Router提供了原生加载状态解决方案,只需在目标路由目录下创建loading.js文件,页面加载时会自动渲染该组件:

// app/words/loading.js
export default function Loading() {
  return (
    <div className="flex justify-center items-center h-screen">
      <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
      <p className="ml-3">正在加载单词列表...</p>
    </div>
  );
}

说明:无需手动监听路由,Next.js会自动处理加载状态的切换,支持流式渲染,是App Router下的最优解。可在不同路由目录创建专属loading组件,也可在根目录设置全局加载提示。

3. 自定义带加载状态的跳转组件

如果需要针对特定跳转做定制化反馈,可以封装自己的跳转组件,点击时立即触发加载状态:

import { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import LoadingButton from '../components/LoadingButton';

export default function CustomLink({ href, children }) {
  const [isLoading, setIsLoading] = useState(false);
  const router = useRouter();

  const handleClick = async (e) => {
    setIsLoading(true);
    try {
      await router.push(href);
    } catch (err) {
      console.error('跳转失败:', err);
    } finally {
      setIsLoading(false);
    }
  };

  return isLoading ? (
    <LoadingButton>{children}</LoadingButton>
  ) : (
    <Link href={href} onClick={handleClick}>
      {children}
    </Link>
  );
}

说明:适合需要点击后立即反馈的场景,比如你提到的“查找所有以a开头的单词”按钮,点击后可直接切换为加载状态按钮,避免用户重复操作。

4. 全局顶部进度条

如果想要更细腻的加载感知,可以实现一个顶部进度条:

// _app.js (Pages Router)
import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';

function MyApp({ Component, pageProps }) {
  const [progress, setProgress] = useState(0);
  const router = useRouter();

  useEffect(() => {
    const handleStart = () => {
      setProgress(30);
      const timer = setInterval(() => {
        setProgress(prev => prev < 90 ? prev + 10 : 90);
      }, 100);
      return () => clearInterval(timer);
    };

    const handleComplete = () => {
      setProgress(100);
      setTimeout(() => setProgress(0), 300);
    };

    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleComplete);
    router.events.on('routeChangeError', handleComplete);

    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleComplete);
      router.events.off('routeChangeError', handleComplete);
    };
  }, [router]);

  return (
    <>
      {progress > 0 && (
        <div className="fixed top-0 left-0 right-0 h-1 bg-blue-500 z-50" 
             style={{ width: `${progress}%`, transition: 'width 0.2s ease' }}></div>
      )}
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

说明:顶部进度条能给用户更直观的加载节奏感知,避免用户误以为页面无响应。

内容的提问来源于stack exchange,提问作者Lance Pollard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:32:05