Lenis平滑滚动导致Next.js路由切换无法自动滚动至顶部的问题求助
解决Next.js集成Lenis后Link导航不滚动到顶部的问题
当Next.js项目集成Lenis实现平滑滚动后,使用Link组件导航时,滚动位置会停留在上一页的位置,而非默认回到页面顶部。这是因为Lenis接管了原生滚动行为,覆盖了Next.js默认的路由切换滚动逻辑。以下是可行的解决方案:
方案一:Pages Router(_app.js)
在你的_app.js中,通过监听Next.js路由切换事件,手动触发Lenis滚动到顶部,同时完善实例销毁逻辑:
import { useRouter } from 'next/router'; import { useIsomorphicLayoutEffect } from './your-hooks-path'; // 替换为你的useIsomorphicLayoutEffect实际路径 import Lenis from '@studio-freight/lenis'; function MyApp({ Component, pageProps }) { const router = useRouter(); useIsomorphicLayoutEffect(() => { const lenis = new Lenis({ duration: 2.5, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) }); // 启动Lenis的requestAnimationFrame循环 function raf(time) { lenis.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); // 路由切换完成后滚动到顶部 const handleRouteChange = () => { lenis.scrollTo(0, { immediate: true }); }; router.events.on('routeChangeComplete', handleRouteChange); // 清理函数:销毁Lenis实例并移除事件监听 return () => { lenis.destroy(); router.events.off('routeChangeComplete', handleRouteChange); }; }, [router]); return <Component {...pageProps} />; } export default MyApp;
关键说明:
routeChangeComplete事件会在页面导航完成后触发,此时调用lenis.scrollTo(0, { immediate: true })强制立即滚动到顶部(避免平滑动画影响页面切换体验)。- 必须在组件卸载时调用
lenis.destroy()并移除事件监听,防止内存泄漏。
方案二:App Router(Next.js 13+)
如果使用App Router,在客户端组件的Layout中通过usePathname监听路径变化,触发滚动:
'use client'; import { usePathname } from 'next/navigation'; import Lenis from '@studio-freight/lenis'; import { useEffect, useRef } from 'react'; export default function RootLayout({ children }) { const lenisRef = useRef(null); const pathname = usePathname(); useEffect(() => { // 初始化Lenis实例 if (!lenisRef.current) { lenisRef.current = new Lenis({ duration: 2.5, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) }); function raf(time) { lenisRef.current.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); } // 路径变化时滚动到顶部 lenisRef.current.scrollTo(0, { immediate: true }); // 清理实例 return () => { lenisRef.current?.destroy(); }; }, [pathname]); return ( <html lang="en"> <body>{children}</body> </html> ); }
关键说明:
usePathname会在路由切换时更新,触发useEffect回调,此时调用Lenis的scrollTo方法。- 使用
useRef保存Lenis实例,避免每次路径变化都重新创建实例。
内容的提问来源于stack exchange,提问作者Joshua Thompson
相关产品推荐
相关产品推荐

