返回首页

Next.js 中的 useAnchorObserver 锚点导航

本文描述了在单页 Next.js 应用中使用 useAnchorObserver 钩子实现锚点导航。滚动和 URL 同步自动化,支持浏览器历史和 SEO。提供完整的代码和设置。

Next.js 单页应用:无 bug 锚点导航
Advertisement 728x90

Next.js 单页应用中的锚点导航实现

在 Next.js 单页应用中,锚点导航可实现页面不同区域间的平滑切换,无需重新加载页面。react-use-observer-hooks 库中的 useAnchorObserver 钩子自动处理滚动与 URL 同步:它能在滚动时检测当前可见区域,并在地址变化时自动滚动至对应锚点。

该机制双向工作:滚动通过 IntersectionObserver 更新 URL,而 URL 变化(来自点击或后退按钮)则触发滚动至对应区域。这避免了反馈循环,并确保浏览器历史记录的正确处理。

项目设置

使用 Next.js 15(Pages Router)、React 19 和 Tailwind CSS v4。安装依赖:

Google AdInline article slot
npm install react-use-observer-hooks

next.config.ts 中禁用内置的滚动恢复功能,以避免与钩子冲突:

const nextConfig = {
  experimental: {
    scrollRestoration: false,
  },
};

创建一个全捕获路由 [[...slug]].tsx,以在单页上处理类似 //about/contact 的路径。

主页面代码

定义包含 href、标签和组件的区域数组:

Google AdInline article slot
import { useAnchorObserver } from 'react-use-observer-hooks';
import { useRouter } from 'next/router';

const SECTIONS = [
  { href: '/',        label: '首页',    Component: HomeSection },
  { href: '/about',   label: '关于',   Component: AboutSection },
  { href: '/contact', label: '加入我们', Component: ContactSection },
];

export default function Page() {
  const router = useRouter();

  const { ref, focusedAnchor } = useAnchorObserver<HTMLDivElement>({
    anchors: SECTIONS.map(s => s.href),
    currentAnchor: router.asPath,
    onAnchorChange: (anchor) => {
      router.push(anchor, undefined, { scroll: false, shallow: true });
    },
  });

  return (
    <>
      <Navbar sections={SECTIONS} activeHref={focusedAnchor} />

      <div ref={ref}>
        {SECTIONS.map(({ href, Component }) => (
          <section key={href} style={{ minHeight: '100vh' }}>
            <Component />
          </section>
        ))}
      </div>
    </>
  );
}

关键点:

  • ref 应用于区域容器。钩子通过索引将直接子元素映射到 anchors 数组。
  • router.push 中的 scroll: false 防止 Next.js 自动滚动。
  • shallow: true 优化导航,避免服务器重新渲染。

导航组件

导航栏使用具有相同选项的 <Link>

import Link from 'next/link';

export const Navbar = ({ sections, activeHref }) => (
  <nav>
    {sections.map(({ href, label }) => (
      <Link
        key={href}
        href={href}
        scroll={false}
        shallow
        className={activeHref === href ? 'active' : ''}
      >
        {label}
      </Link>
    ))}
  </nav>
);

focusedAnchor 根据可见区域自动高亮活动项。

Google AdInline article slot

应用行为

最终实现提供:

  • 直接访问 /about 等链接,准确跳转至对应区域。
  • 正确的浏览器后退按钮功能。
  • 搜索引擎索引支持,具有唯一 URL。
  • 菜单与可见内容同步。

要点总结

  • useAnchorObserver 钩子完全自动化双向滚动与 URL 同步。
  • 禁用 scrollRestoration 至关重要,以避免冲突。
  • Pages Router 中的全捕获路由适用于类 SPA 导航。
  • shallow: true + scroll: false 最小化重新渲染。
  • 浏览器历史记录和 SEO 支持开箱即用。

— Editorial Team

Advertisement 728x90

继续阅读