NextJS 中的页面过渡效果

2025-06-08

NextJS 中的页面过渡效果

由于提供了新的 API,因此此方法可能不是 NextJS v12+ 的最佳方法。

在我们开始为过渡构建任何组件之前,让我们简单讨论一下 NextJS 如何渲染页面。

首先,让我们看一下_app.js

export default function MyApp({ Component, pageProps }) {
  return (
      <Component {...pageProps} />
  );
}

Enter fullscreen mode Exit fullscreen mode

“_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>
  );
}

Enter fullscreen mode Exit fullscreen mode

并添加到_app.js

function MyApp({ Component, pageProps }) {
  return (
    <TransitionLayout>
      <Component {...pageProps} />
    </TransitionLayout>
  );
}
Enter fullscreen mode Exit fullscreen mode

现在,让我们开始TransitionLayout

首先,我们需要阻止渲染新页面

我们可以添加一个状态来保存当前子项,并且仅渲染displayChildren

我们使用children为默认值displayChildren


export default function TransitionLayout({ children }) {
  const [displayChildren, setDisplayChildren] = useState(children);
  return (
    <div>
      ...
      <div>
        {displayChildren}
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

现在,如果您单击该链接,页面内容将不会改变。

接下来我们添加 css 和过渡阶段

.content {
  opacity: 0;
  background-color: cornflowerblue;
  transition: 1s;
}

.fadeIn {
  opacity: 1;
}

Enter fullscreen mode Exit fullscreen mode
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>
  );
}
Enter fullscreen mode Exit fullscreen mode

现在组件默认处于淡出阶段,我们想让它在第一次渲染时进入淡入阶段,所以我们添加:

  useEffect(() => {
    setTransitionStage("fadeIn");
  }, []);

Enter fullscreen mode Exit fullscreen mode

接下来,我们希望组件在接收到新的子组件时进入“淡出”状态。

  useEffect(() => {
    if (children !== displayChildren) setTransitionStage("fadeOut");
  }, [children, setDisplayChildren, displayChildren]);

Enter fullscreen mode Exit fullscreen mode

并且,在“淡出”完成时渲染新的子项,然后重新进入“淡入”阶段。

  ...
  return(
      ...
      <div
        onTransitionEnd={() => {
          if (transitionStage === "fadeOut") {
            console.log("fading out");
            setDisplayChildren(children);
            setTransitionStage("fadeIn");
          }
        }}
        className={`${styles.content} ${styles[transitionStage]}`}
      >
        {displayChildren}
      </div>
  )
Enter fullscreen mode Exit fullscreen mode

以下是布局组件的演示和完整代码:
节点:演示将需要一些时间才能让 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>
  );
}


Enter fullscreen mode Exit fullscreen mode

谢谢大家!!

鏂囩珷鏉ユ簮锛�https://dev.to/anxiny/page-transition-effect-in-nextjs-9ch
PREV
如何通过 5 个步骤从编程教程过渡到开发应用程序 问题 解决方案 从编程教程过渡到开发应用程序的 5 个步骤 要点
NEXT
一种简洁的条件渲染组件的方法