App下載

如何在 Next.js 項(xiàng)目中制作自定義加載屏幕

嘴角的櫻桃汁 2021-08-30 12:02:12 瀏覽數(shù) (2664)
反饋

介紹

Next.js 是一個(gè)建立在 Node.js 之上的開源開發(fā)框架,支持基于 React 的 Web 應(yīng)用程序功能,例如服務(wù)器端渲染和生成靜態(tài)網(wǎng)站。

我試圖在 Next.js 中為我的項(xiàng)目構(gòu)建一個(gè)自定義加載屏幕,所以我嘗試谷歌我們?nèi)绾螌?shí)現(xiàn)它,經(jīng)過(guò)數(shù)小時(shí)的搜索,我無(wú)法找到適合我需要的解決方案。我在互聯(lián)網(wǎng)上遇到了一個(gè)解決方案,它使用一個(gè)名為“nprogress”的庫(kù)來(lái)執(zhí)行此操作,但它沒(méi)有提供我想要實(shí)現(xiàn)的加載屏幕,因此在瀏覽 Next.js 文檔和這個(gè)“nprogress”解決方案后,我能夠找出解決問(wèn)題的方法。我花了很多時(shí)間,所以我創(chuàng)建了這個(gè)博客來(lái)幫助任何想要在更短的時(shí)間內(nèi)輕松地在 Next.js 中實(shí)現(xiàn)自定義加載屏幕的人。

制作自定義加載屏幕組件

這部分完全取決于您以及您希望加載屏幕組件的外觀。例如下面是我的加載組件:

import React from "react";
import styles from "./Loading.module.css";

function Loading(props) {
  return (
    <div className={props.loading ? styles.body_loading : styles.none}>
      <div
        className={styles.lds_ellipsis}
      >
        <div></div>
        <div></div>
        <div></div>
        <div></div>
      </div>
    </div>
  );
}

export default Loading;

加載組件的樣式 (CSS):

.body_loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}
.none {
  display: none;
}
.lds_ellipsis {
  display: inline-block;
  position: relative;
  width: 80px;
  height: 80px;
}
.lds_ellipsis div {
  position: absolute;
  top: 33px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--orange);
  animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
.lds_ellipsis div:nth-child(1) {
  left: 8px;
  animation: lds_ellipsis1 0.6s infinite;
}
.lds_ellipsis div:nth-child(2) {
  left: 8px;
  animation: lds_ellipsis2 0.6s infinite;
}
.lds_ellipsis div:nth-child(3) {
  left: 32px;
  animation: lds_ellipsis2 0.6s infinite;
}
.lds_ellipsis div:nth-child(4) {
  left: 56px;
  animation: lds_ellipsis3 0.6s infinite;
}
@keyframes lds_ellipsis1 {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}
@keyframes lds_ellipsis3 {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(0);
  }
}
@keyframes lds_ellipsis2 {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(24px, 0);
  }
}

因此,您已經(jīng)成功地使用自定義樣式構(gòu)建了加載屏幕組件,現(xiàn)在是時(shí)候在每次路由更改時(shí)在 Web 應(yīng)用程序上呈現(xiàn)它了。

為此,我們將借助 Next.js 路由器事件,您可以偵聽(tīng) Next.js 路由器內(nèi)部發(fā)生的不同事件。

以下是支持的事件列表:

routeChangeStart(url, { shallow }) - Fires when a route starts to change

routeChangeComplete(url, { shallow }) - Fires when a route changed completely

routeChangeError(err, url, { shallow }) - Fires when there's an error when changing routes, or a route load is cancelled

err.cancelled - Indicates if the navigation was cancelled

beforeHistoryChange(url, { shallow }) - Fires before changing the browser's history

hashChangeStart(url, { shallow }) - Fires when the hash will change but not the page

hashChangeComplete(url, { shallow }) - Fires when the hash has changed but not the page

有關(guān)這些事件和其他路由器方法的更多詳細(xì)信息,您可以訪問(wèn)Next.js 官方文檔

借助這些事件,您可以將加載屏幕組件添加到 app.js 中,看看如何:

首先導(dǎo)入{useState, useEffect}from "react"{useRouter}from"next/router"和您的Loading組件。

import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import Loading from "../components/Loading";

現(xiàn)在我們將loading使用useState鉤子聲明變量并使用它進(jìn)行初始化false,我們將true在路由更改時(shí)將其設(shè)置為,并在路由更改完成后將其恢復(fù)為 false。

我們將把這個(gè)邏輯放在useEffecthook 中并設(shè)置router為它的依賴項(xiàng)。這意味著每次router更改useEffect鉤子內(nèi)的邏輯都會(huì)被執(zhí)行。

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

useEffect(() => {
    const handleStart = (url) => {
      url !== router.pathname ? setLoading(true) : setLoading(false);
    };
    const handleComplete = (url) => setLoading(false);

    router.events.on("routeChangeStart", handleStart);
    router.events.on("routeChangeComplete", handleComplete);
    router.events.on("routeChangeError", handleComplete);
  }, [router]);

  return (
    <>
          <Loading loading={loading} />  
          <Component {...pageProps} />
    </>
  );
}

export default MyApp;
}

我們將通過(guò)loading變量為道具,以我們的Loading組件,以便隨時(shí)loadingtrue Loading組件將已經(jīng)classdisplay: block當(dāng)它是false將有classdisplay: none。



1 人點(diǎn)贊