介绍
Next.js 是一个建立在 Node.js 之上的开源开发框架,支持基于 React 的 Web 应用程序功能,例如服务器端渲染和生成静态网站。
我试图在 Next.js 中为我的项目构建一个自定义加载屏幕,所以我尝试谷歌我们如何实现它,经过数小时的搜索,我无法找到适合我需要的解决方案。我在互联网上遇到了一个解决方案,它使用一个名为“nprogress”的库来执行此操作,但它没有提供我想要实现的加载屏幕,因此在浏览 Next.js 文档和这个“nprogress”解决方案后,我能够找出解决问题的方法。我花了很多时间,所以我创建了这个博客来帮助任何想要在更短的时间内轻松地在 Next.js 中实现自定义加载屏幕的人。
制作自定义加载屏幕组件
这部分完全取决于您以及您希望加载屏幕组件的外观。例如下面是我的加载组件:
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);
}
}
因此,您已经成功地使用自定义样式构建了加载屏幕组件,现在是时候在每次路由更改时在 Web 应用程序上呈现它了。
为此,我们将借助 Next.js 路由器事件,您可以侦听 Next.js 路由器内部发生的不同事件。
以下是支持的事件列表:
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
有关这些事件和其他路由器方法的更多详细信息,您可以访问Next.js 官方文档
借助这些事件,您可以将加载屏幕组件添加到 app.js 中,看看如何:
首先导入{useState, useEffect}
from "react"
,{useRouter}
from"next/router"
和您的Loading
组件。
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import Loading from "../components/Loading";
现在我们将loading
使用useState
钩子声明变量并使用它进行初始化false
,我们将true
在路由更改时将其设置为,并在路由更改完成后将其恢复为 false。
我们将把这个逻辑放在useEffect
hook 中并设置router
为它的依赖项。这意味着每次router
更改useEffect
钩子内的逻辑都会被执行。
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;
}
我们将通过loading
变量为道具,以我们的Loading
组件,以便随时loading
为true
Loading
组件将已经class
有display: block
当它是false
将有class
有display: none
。