You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 20:50:23