介绍
Next.js 是一个建立在 Node.js 之上的开源开发框架,支持基于 React 的 Web 应用程序功能,例如服务器端渲染和生成静态网站。
我试图在 Next.js 中为我的项目构建一个自定义加载屏幕,所以我尝试谷歌我们如何实现它,经过数小时的搜索,我无法找到适合我需要的解决方案。我在互联网上遇到了一个解决方案,它使用一个名为“nprogress”的库来执行此操作,但它没有提供我想要实现的加载屏幕,因此在浏览 Next.js 文档和这个“nprogress”解决方案后,我能够找出解决问题的方法。我花了很多时间,所以我创建了这个博客来帮助任何想要在更短的时间内轻松地在 Next.js 中实现自定义加载屏幕的人。
制作自定义加载屏幕组件
这部分完全取决于您以及您希望加载屏幕组件的外观。例如下面是我的加载组件:
<span style="color:#333333"><span style="background-color:#ffffff"><span style="background-color:#201e2f"><span style="color:#f8f8f2"><code><span style="color:#f92672">import</span> React <span style="color:#f92672">from</span> <span style="color:#e6db74">"</span><span style="color:#e6db74">react</span><span style="color:#e6db74">"</span>;
<span style="color:#f92672">import</span> styles <span style="color:#f92672">from</span> <span style="color:#e6db74">"</span><span style="color:#e6db74">./Loading.module.css</span><span style="color:#e6db74">"</span>;
<span style="color:#f92672">function</span> <span style="color:#a6e22e">Loading</span>(<span style="color:#f8f8f2">props</span>) {
<span style="color:#f92672">return</span> (
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important"><span style="color:#f92672">div</span></span> <span style="color:#f8f8f2 !important"><span style="color:#f92672">className</span></span><span style="color:#f8f8f2 !important">=</span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">{</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">props</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">.</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">loading</span></span> <span style="color:#f8f8f2 !important">?</span> <span style="color:#f8f8f2 !important"><span style="color:#f92672">styles</span></span><span style="color:#f8f8f2 !important"><span style="color:#f92672">.</span></span><span style="color:#f8f8f2 !important"><span style="color:#f92672">body_loading</span></span> <span style="color:#f8f8f2 !important"><span style="color:#f92672">:</span></span> <span style="color:#f8f8f2 !important"><span style="color:#f92672">styles</span></span><span style="color:#f8f8f2 !important"><span style="color:#f92672">.</span></span><span style="color:#f8f8f2 !important"><span style="color:#f92672">none</span></span><span style="color:#f8f8f2 !important">}</span><span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important"><span style="color:#f92672">div</span></span>
<span style="color:#f8f8f2 !important"><span style="color:#f92672">className</span></span><span style="color:#f8f8f2 !important">=</span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">{</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">styles</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">.</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">lds_ellipsis</span></span><span style="color:#f8f8f2 !important"><span style="color:#e6db74">}</span></span>
<span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important"><span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span><span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important">/<span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important"><span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span><span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important">/<span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important"><span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span><span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important">/<span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important"><span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span><span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important">/<span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important">/<span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span>
<span style="color:#f8f8f2 !important"><</span><span style="color:#f8f8f2 !important">/<span style="color:#f92672">div</span></span><span style="color:#f8f8f2 !important">></span>
);
}
<span style="color:#f92672">export</span> <span style="color:#f92672">default</span> Loading;</code></span></span></span></span>
加载组件的样式 (CSS):
<span style="color:#333333"><span style="background-color:#ffffff"><span style="background-color:#201e2f"><span style="color:#f8f8f2"><code><span style="color:#a6e22e">.body_loading</span> {
<span style="color:#66d9ef">display</span>: flex;
<span style="color:#66d9ef">align-items</span>: center;
<span style="color:#66d9ef">justify-content</span>: center;
<span style="color:#66d9ef">height</span>: <span style="color:#ae81ff">100vh</span>;
}
<span style="color:#a6e22e">.none</span> {
<span style="color:#66d9ef">display</span>: none;
}
<span style="color:#a6e22e">.lds_ellipsis</span> {
<span style="color:#66d9ef">display</span>: inline-block;
<span style="color:#66d9ef">position</span>: relative;
<span style="color:#66d9ef">width</span>: <span style="color:#ae81ff">80px</span>;
<span style="color:#66d9ef">height</span>: <span style="color:#ae81ff">80px</span>;
}
<span style="color:#a6e22e">.lds_ellipsis</span> <span style="color:#f92672">div</span> {
<span style="color:#66d9ef">position</span>: absolute;
<span style="color:#66d9ef">top</span>: <span style="color:#ae81ff">33px</span>;
<span style="color:#66d9ef">width</span>: <span style="color:#ae81ff">15px</span>;
<span style="color:#66d9ef">height</span>: <span style="color:#ae81ff">15px</span>;
<span style="color:#66d9ef">border-radius</span>: <span style="color:#ae81ff">50%</span>;
<span style="color:#66d9ef">background</span>: <span style="color:#e6db74">var</span>(--orange);
<span style="color:#66d9ef">animation-timing-function</span>: <span style="color:#e6db74">cubic-bezier</span>(0, 1, 1, 0);
}
<span style="color:#a6e22e">.lds_ellipsis</span> <span style="color:#f92672">div</span><span style="color:#e6db74">:nth-child</span><span style="color:#e6db74">(</span><span style="color:#e6db74">1</span><span style="color:#e6db74">)</span> {
<span style="color:#66d9ef">left</span>: <span style="color:#ae81ff">8px</span>;
<span style="color:#66d9ef">animation</span>: lds_ellipsis1 <span style="color:#ae81ff">0.6s</span> infinite;
}
<span style="color:#a6e22e">.lds_ellipsis</span> <span style="color:#f92672">div</span><span style="color:#e6db74">:nth-child</span><span style="color:#e6db74">(</span><span style="color:#e6db74">2</span><span style="color:#e6db74">)</span> {
<span style="color:#66d9ef">left</span>: <span style="color:#ae81ff">8px</span>;
<span style="color:#66d9ef">animation</span>: lds_ellipsis2 <span style="color:#ae81ff">0.6s</span> infinite;
}
<span style="color:#a6e22e">.lds_ellipsis</span> <span style="color:#f92672">div</span><span style="color:#e6db74">:nth-child</span><span style="color:#e6db74">(</span><span style="color:#e6db74">3</span><span style="color:#e6db74">)</span> {
<span style="color:#66d9ef">left</span>: <span style="color:#ae81ff">32px</span>;
<span style="color:#66d9ef">animation</span>: lds_ellipsis2 <span style="color:#ae81ff">0.6s</span> infinite;
}
<span style="color:#a6e22e">.lds_ellipsis</span> <span style="color:#f92672">div</span><span style="color:#e6db74">:nth-child</span><span style="color:#e6db74">(</span><span style="color:#e6db74">4</span><span style="color:#e6db74">)</span> {
<span style="color:#66d9ef">left</span>: <span style="color:#ae81ff">56px</span>;
<span style="color:#66d9ef">animation</span>: lds_ellipsis3 <span style="color:#ae81ff">0.6s</span> infinite;
}
@<span style="color:#f92672">keyframes</span> lds_ellipsis1 {
0% {
<span style="color:#66d9ef">transform</span>: <span style="color:#e6db74">scale</span>(0);
}
100% {
<span style="color:#66d9ef">transform</span>: <span style="color:#e6db74">scale</span>(1);
}
}
@<span style="color:#f92672">keyframes</span> lds_ellipsis3 {
0% {
<span style="color:#66d9ef">transform</span>: <span style="color:#e6db74">scale</span>(1);
}
100% {
<span style="color:#66d9ef">transform</span>: <span style="color:#e6db74">scale</span>(0);
}
}
@<span style="color:#f92672">keyframes</span> lds_ellipsis2 {
0% {
<span style="color:#66d9ef">transform</span>: <span style="color:#e6db74">translate</span>(0, 0);
}
100% {
<span style="color:#66d9ef">transform</span>: <span style="color:#e6db74">translate</span>(24px, 0);
}
}</code></span></span></span></span>
因此,您已经成功地使用自定义样式构建了加载屏幕组件,现在是时候在每次路由更改时在 Web 应用程序上呈现它了。
为此,我们将借助 Next.js 路由器事件,您可以侦听 Next.js 路由器内部发生的不同事件。
以下是支持的事件列表:
<span style="color:#333333"><span style="background-color:#ffffff"><span style="background-color:#201e2f"><span style="color:#f8f8f2"><code>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<span style="color:#e6db74">'s an error when changing routes, or a route load is cancelled</span>
<span style="color:#e6db74">
err.cancelled - Indicates if the navigation was cancelled</span>
<span style="color:#e6db74">
beforeHistoryChange(url, { shallow }) - Fires before changing the browser'</span>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</code></span></span></span></span>
有关这些事件和其他路由器方法的更多详细信息,您可以访问Next.js 官方文档
借助这些事件,您可以将加载屏幕组件添加到 app.js 中,看看如何:
首先导入{useState, useEffect}from "react",{useRouter}from"next/router"和您的Loading组件。
<span style="color:#333333"><span style="background-color:#ffffff"><span style="background-color:#201e2f"><span style="color:#f8f8f2"><code><span style="color:#f92672">import</span> { useState, useEffect } <span style="color:#f92672">from</span> <span style="color:#e6db74">"</span><span style="color:#e6db74">react</span><span style="color:#e6db74">"</span>;
<span style="color:#f92672">import</span> { useRouter } <span style="color:#f92672">from</span> <span style="color:#e6db74">"</span><span style="color:#e6db74">next/router</span><span style="color:#e6db74">"</span>;
<span style="color:#f92672">import</span> Loading <span style="color:#f92672">from</span> <span style="color:#e6db74">"</span><span style="color:#e6db74">../components/Loading</span><span style="color:#e6db74">"</span>;</code></span></span></span></span>
现在我们将loading使用useState钩子声明变量并使用它进行初始化false,我们将true在路由更改时将其设置为,并在路由更改完成后将其恢复为 false。
我们将把这个逻辑放在useEffecthook 中并设置router为它的依赖项。这意味着每次router更改useEffect钩子内的逻辑都会被执行。
<span style="color:#333333"><span style="background-color:#ffffff"><span style="background-color:#201e2f"><span style="color:#f8f8f2"><code><span style="color:#f92672">function</span> <span style="color:#a6e22e">MyApp</span>(<span style="color:#f8f8f2">{</span> <span style="color:#f8f8f2">Component</span><span style="color:#f8f8f2">,</span> <span style="color:#f8f8f2">pageProps</span> <span style="color:#f8f8f2">}</span>) {
<span style="color:#f92672">const</span> router = useRouter();
<span style="color:#f92672">const</span> [loading, setLoading] = useState(<span style="color:#ae81ff">false</span>);
useEffect(() => {
<span style="color:#f92672">const</span> handleStart = (url) => {
url !== router.pathname ? setLoading(<span style="color:#ae81ff">true</span>) : setLoading(<span style="color:#ae81ff">false</span>);
};
<span style="color:#f92672">const</span> handleComplete = (url) => setLoading(<span style="color:#ae81ff">false</span>);
router.events.on(<span style="color:#e6db74">"</span><span style="color:#e6db74">routeChangeStart</span><span style="color:#e6db74">"</span>, handleStart);
router.events.on(<span style="color:#e6db74">"</span><span style="color:#e6db74">routeChangeComplete</span><span style="color:#e6db74">"</span>, handleComplete);
router.events.on(<span style="color:#e6db74">"</span><span style="color:#e6db74">routeChangeError</span><span style="color:#e6db74">"</span>, handleComplete);
}, [router]);
<span style="color:#f92672">return</span> (
<>
<Loading loading={loading} />
<Component {...pageProps} />
</>
);
}
export default MyApp;
}</code></span></span></span></span>
我们将通过loading变量为道具,以我们的Loading组件,以便随时loading为true Loading组件将已经class有display: block当它是false将有class有display: none。
结论
这是在 Next.js 中制作自定义加载屏幕的方法。我希望这个博客可以帮助您并节省您的时间和精力。
本文介绍了如何在 Next.js 项目中构建自定义加载屏幕组件,通过利用 Next.js 的路由事件监听,实现页面路由变化时显示加载屏幕。详细步骤包括组件样式设计、事件监听以及在 app.js 中的实现方法。

被折叠的 条评论
为什么被折叠?



