如何在Next.js 13中全局实现滚动触发动画(避免全客户端渲染)?
在Next.js 13中全局实现滚动触发动画(AOS)的正确姿势
你担心根组件加'use client'导致全应用客户端渲染的顾虑是对的——确实没必要这么做,下面给你两个更优的方案,既能全局用AOS,又能保留大部分页面的服务器渲染能力:
方案一:全局初始化AOS(仅单个客户端组件)
这个方案只需要一个专门的客户端组件来初始化AOS,根布局依然保持服务器渲染:
- 新建一个客户端组件用于AOS初始化
比如在components/AOSInit.js里写:
'use client'; import { useEffect } from 'react'; import AOS from 'aos'; import 'aos/dist/aos.css'; export default function AOSInit() { useEffect(() => { // 初始化AOS,可根据需求配置参数 AOS.init({ duration: 1000, easing: 'ease-in-out', once: true // 是否只触发一次动画 }); // 监听路由变化,刷新AOS(适配Next.js客户端导航) const { usePathname } = require('next/navigation'); const pathname = usePathname(); useEffect(() => { AOS.refresh(); }, [pathname]); // 组件卸载时销毁AOS实例 return () => { AOS.destroy(); }; }, []); return null; // 该组件无需渲染任何可视内容 }
- 在根布局中引入这个组件
根布局app/layout.js是服务器组件,直接引入上面的客户端组件即可:
import AOSInit from '@/components/AOSInit'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <AOSInit /> {children} </body> </html> ); }
这样一来,只有AOSInit是客户端组件,整个应用的其他页面/组件依然可以保持服务器渲染,所有需要动画的元素直接加data-aos属性就行,比如:
<div data-aos="fade-up">我会在滚动时淡入上移</div>
方案二:封装AOS动画组件(按需使用)
如果不想全局初始化,也可以封装一个可复用的客户端动画组件,其他组件按需引入:
- 封装动画组件
components/AnimatedSection.js
'use client'; import { useEffect } from 'react'; import AOS from 'aos'; import 'aos/dist/aos.css'; export default function AnimatedSection({ animation, children, ...props }) { useEffect(() => { AOS.init(); return () => AOS.destroy(); }, []); return ( <div data-aos={animation} {...props}> {children} </div> ); }
- 在任意组件中使用
不管是服务器组件还是客户端组件,都可以直接引入使用:
import AnimatedSection from '@/components/AnimatedSection'; export default function AboutPage() { return ( <div> <AnimatedSection animation="fade-left"> <h2>关于我们</h2> <p>这是一段会从左侧淡入的内容</p> </AnimatedSection> </div> ); }
关键注意点
- 服务器组件中不能直接调用AOS的API(因为服务器环境没有
window对象),所有AOS相关逻辑必须放在标记了'use client'的组件里 - 用App Router时,客户端路由切换后要调用
AOS.refresh(),否则新页面的动画不会触发 - 确保AOS的CSS文件正确引入,避免动画样式失效
内容的提问来源于stack exchange,提问作者Gal Povsod
相关产品推荐
相关产品推荐

