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

如何在Next.js中实现带路由哈希的平滑滚动?

解决Next.js中哈希路由结合平滑滚动的问题

核心思路

要同时实现地址栏显示哈希链接和平滑滚动,需要手动控制路由哈希更新,同时避免Next.js默认的即时滚动行为,具体方案如下:


步骤1:优化平滑滚动函数

替换原有的scrollTo函数,使用更简洁可靠的scrollIntoView API:

export const scrollTo = (id: string) => {
    const element = document.getElementById(id);
    if (element) {
        element.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
};

步骤2:修改Navigation组件逻辑

在点击导航时,手动更新路由哈希(不触发页面重渲染),同时执行平滑滚动,还要监听路由哈希变化以覆盖初始加载、浏览器前进后退等场景:

import Link from 'next/link';
import React, { useEffect } from 'react';
import _ from 'lodash';
import useAppRouter from '../../../hooks/useAppRouter';
import { scrollTo } from '../path-to-scrollTo'; // 替换为实际文件路径

interface INavigation {
    links: string[];
}

const Navigation: React.FC<INavigation> = ({ links }) => {
    const router = useAppRouter();

    const handleClick = (e: React.MouseEvent<HTMLAnchorElement>, link: string) => {
        e.preventDefault();
        // 用shallow模式更新哈希,不触发页面重渲染
        router.push(`#${link}`, undefined, { shallow: true });
        // 执行平滑滚动
        scrollTo(link);
    };

    // 监听哈希变化,处理初始加载、路由切换场景
    useEffect(() => {
        if (router.hash) {
            const targetId = router.hash.slice(1);
            scrollTo(targetId);
        }
    }, [router.hash]);

    return (
        <section className="stories-navigation">
            <ul>
                {links.map((link: string) => (
                    <li key={link}>
                        <Link href={`#${link}`}>
                            <a
                                onClick={(e) => handleClick(e, link)}
                                className={router.hash === `#${link}` ? 'active-link' : ''}
                            >
                                {_.capitalize(link)}
                            </a>
                        </Link>
                    </li>
                ))}
            </ul>
        </section>
    );
};

export default Navigation;

关键细节说明

  • shallow路由更新:使用router.push的shallow: true参数,仅更新地址栏哈希,不会触发页面重新渲染,保证性能。
  • 哈希匹配修正:router.hash返回的是带#的字符串(如#about),因此激活状态判断需改为router.hash === #${link}``。
  • 全局哈希监听:通过useEffect监听router.hash变化,覆盖所有哈希变更场景(包括手动修改地址栏、浏览器前进后退)。

内容的提问来源于stack exchange,提问作者Yeva Terteryan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:05:49