如何显示我自己的加载程序而不是空白屏幕? 例如,Tweeter 在页面加载时显示徽标,Facebook、谷歌 AdSense 等也是如此。 看这个 Gif,我想要在 Next Js 中出现类似的东西。
我猜这与 _document.js 有关。 React js 有一个类似的问题(在index.html 中渲染加载器) 但我不知道如何在下一个js中做到这一点。
要在 Nextjs 上添加启动屏幕,您可以通过多种方式完成。这是我首选的解决方案。
/**
* inside _app.js function for remove the loader
*/
useEffect(() => {
if (typeof window !== 'undefined') {
const loader = document.getElementById('globalLoader');
if (loader)
loader.remove();
}
}, []);
/* Style.css or global.css */
#globalLoader {
position: fixed;
z-index: 9999;
top: 50%;
left: 50%;
background-color: #fff;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
display: flex;
}
/** * on _document.js insert below code after body tag * More about _document.js -> https://nextjs.org/docs/advanced-features/custom-document */
<div id="globalLoader">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif" alt="" />
</div>
通常这些是通过一个覆盖所有内容并默认显示的 div 来完成的,您在该 div 中放置的内容取决于您(gif、svg 等)。一旦 window.onload 被调用,只需隐藏 div,它将显示完全渲染的 dom。
这是一个基本示例(我在移动设备上,请原谅我的格式) CSS:
.loadingsScreen{
position:absolute;
left:0;
top:0;
width:100%;
height:100%;
background-color: #whatever-color;
z-index: 10; /*just make sure it's the highest on the page*/
}
JS:
window.onload = function(){
$("#loadingScreen").fadeOut(); //just make it hide the overlaying div, I used jQuery in this example but there are many ways to do this
};
无需安装任何库
import { useRouter } from "next/router";
import { useState, useEffect } from "react";
function MyApp() {
const router = useRouter();
const [loading, setLoading] = useState(false);
useEffect(() => {
router.events.on("routeChangeError", (e) => setLoading(false));
router.events.on("routeChangeStart", (e) => setLoading(false));
router.events.on("routeChangeComplete", (e) => setLoading(true));
return () => {
router.events.off("routeChangeError", (e) => setLoading(false));
router.events.off("routeChangeStart", (e) => setLoading(false));
router.events.off("routeChangeComplete", (e) => setLoading(true));
};
}, [router.events]);
return <>{loading ? "loading..." : <AppComponent />}</>;
}
使用suspense,nextjs支持它,但在使用它之前有事情值得考虑。
假设您正在使用带有应用程序目录的 NextJs 13:
在应用程序目录中创建一个文件loading.js或任何名称。这将是您在 DOM 渲染时显示的布局,按照您想要的方式设计它,放置任何需要的 gif/svgs。
loading.js
export default function Loading() {
return (
<div className="fixed inset-0 bg-blue-500 z-[10000] flex flex-1 items-center justify-center">
Loading
</div>
);
}
那么你的布局文件应该如下所示:
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Suspense fallback={<Loading />}>{children}</Suspense>
</body>
</html>
);
}
只要你的 DOM 被渲染消失,你就会看到它在某些上像 fla 一样渲染,而在另一些上则很慢,这取决于你的页面大小。如果需要,您可以查找、延迟 Suspense 或添加惰性组件。
提示:使用 Lottie 动画来制作加载或任何较小尺寸的 svg,并且旋转使用 css 动画来保持悬念内容更小。
实际上这不是 Next.js 提供的“开箱即用”的东西,你必须自己实现这些东西,你可以使用一些全局状态(redux/context)来确定你的应用程序是否正在加载某些东西,并基于渲染加载器就这个状态。
试试这个逻辑。创建一个状态变量并使用 NextJs Router 事件。使用路由器事件来控制状态变量,最后使用状态变量来控制加载屏幕和其他 DOM 元素的渲染。
function MyApp(){
const [loading, setLoading] = React.useState<boolean>(false);
Router.events.on('routeChangeStart', (url) => {
setLoading(true);
});
Router.events.on('routeChangeComplete', (url) => {
setLoading(false);
});
return(
<>
{loading ? (
<PageLoader />
) : (
<AppLayout>
<Component {...pageProps} />
</AppLayout>
)}
</>
)
}
你不能。您看到的是 twitch 加载程序向您显示的自定义启动屏幕。它的作用是将加载过程分为两部分。第一个是标准的 - 浏览器请求并接收您提供的用于呈现页面的 html 和脚本文件。您无法使用传统的 Web 应用程序绕过此阶段,但是为了改善用户体验,您可以做的是最大限度地减少该时间。一个很好的例子是一个包含内联 css 和 javascript 的 index.html,它们可以为启动屏幕设置动画,一旦加载就会启动实际的应用程序。这样,真正的数据交换是在浏览器呈现页面之后完成的。这需要您在规划应用程序时做大量工作,但使用现代框架和工具肯定有更短、更脏的路径来实现它。然而,如果您有 SPA,这几乎是您唯一可以选择的方法。
顺便说一句,如果您想加快网站的加载速度(这就是为什么需要启动屏幕),只需运行一些分析,检查优化即可。服务器端缓存通常可以为您提供最佳的投资回报率,但它不会帮助您处理较重的负载(大图像或大量小图像)。 html 分段是第二好的选择。然后你应该看看导入的库和东西,这些往往会增加一些。最后还有一些选项可以压缩服务器上的数据以限制数据负载。
您可以使用router.event。
请参阅此链接:
https://github.com/vercel/next.js/blob/canary/examples/with-loading/pages/_app.js
useEffect(() => { const handleStart = (url) => { 控制台.log(
Loading: ${url}
)
NProgress.start()
}
常量handleStop = () => {
NProgress.done()
}
router.events.on('routeChangeStart', handleStart)
router.events.on('routeChangeComplete', handleStop)
router.events.on('routeChangeError', handleStop)
return () => {
router.events.off('routeChangeStart', handleStart)
router.events.off('routeChangeComplete', handleStop)
router.events.off('routeChangeError', handleStop)
}
},[路由器]);