NextJS 中的页面过渡效果
由于提供了新的 API,因此此方法可能不是 NextJS v12+ 的最佳方法。
在我们开始为过渡构建任何组件之前,让我们简单讨论一下 NextJS 如何渲染页面。
首先,让我们看一下_app.js
:
export default function MyApp({ Component, pageProps }) {
return (
<Component {...pageProps} />
);
}
“_app.js” 是 NextJS 启动渲染页面的入口。当你导航到其他页面时,页面组件会以 的形式传递给 MyApp Component
。
因此,为了制作过渡效果,我们需要阻止
NextJS 在过渡效果完成之前渲染新页面。
现在,让我们创建带有一些导航链接的布局组件:
export default function TransitionLayout({ children }) {
return (
<div>
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
</nav>
<div>
{children}
</div>
</div>
);
}
并添加到_app.js
function MyApp({ Component, pageProps }) {
return (
<TransitionLayout>
<Component {...pageProps} />
</TransitionLayout>
);
}
现在,让我们开始TransitionLayout
首先,我们需要阻止渲染新页面
我们可以添加一个状态来保存当前子项,并且仅渲染displayChildren
。
我们使用children
为默认值displayChildren
。
export default function TransitionLayout({ children }) {
const [displayChildren, setDisplayChildren] = useState(children);
return (
<div>
...
<div>
{displayChildren}
</div>
</div>
);
}
现在,如果您单击该链接,页面内容将不会改变。
接下来我们添加 css 和过渡阶段
.content {
opacity: 0;
background-color: cornflowerblue;
transition: 1s;
}
.fadeIn {
opacity: 1;
}
export default function TransitionLayout({ children }) {
const [displayChildren, setDisplayChildren] = useState(children);
const [transitionStage, setTransitionStage] = useState("fadeOut");
...
return (
<div>
...
<div
className={`${styles.content} ${styles[transitionStage]}`}
>
{displayChildren}
</div>
</div>
);
}
现在组件默认处于淡出阶段,我们想让它在第一次渲染时进入淡入阶段,所以我们添加:
useEffect(() => {
setTransitionStage("fadeIn");
}, []);
接下来,我们希望组件在接收到新的子组件时进入“淡出”状态。
useEffect(() => {
if (children !== displayChildren) setTransitionStage("fadeOut");
}, [children, setDisplayChildren, displayChildren]);
并且,在“淡出”完成时渲染新的子项,然后重新进入“淡入”阶段。
...
return(
...
<div
onTransitionEnd={() => {
if (transitionStage === "fadeOut") {
console.log("fading out");
setDisplayChildren(children);
setTransitionStage("fadeIn");
}
}}
className={`${styles.content} ${styles[transitionStage]}`}
>
{displayChildren}
</div>
)
以下是布局组件的演示和完整代码:
节点:演示将需要一些时间才能让 CodeSandbox 启动。
import Link from "next/link";
import { useState, memo, useEffect } from "react";
import styles from "./Layout.module.css";
export default function TransitionLayout({ children }) {
const [displayChildren, setDisplayChildren] = useState(children);
const [transitionStage, setTransitionStage] = useState("fadeOut");
useEffect(() => {
setTransitionStage("fadeIn");
}, []);
useEffect(() => {
if (children !== displayChildren) setTransitionStage("fadeOut");
}, [children, setDisplayChildren, displayChildren]);
return (
<div>
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
</nav>
<div
onTransitionEnd={() => {
if (transitionStage === "fadeOut") {
console.log("fading out");
setDisplayChildren(children);
setTransitionStage("fadeIn");
}
}}
className={`${styles.content} ${styles[transitionStage]}`}
>
{displayChildren}
</div>
</div>
);
}
谢谢大家!!
鏂囩珷鏉ユ簮锛�https://dev.to/anxiny/page-transition-effect-in-nextjs-9ch