Next.js 单页应用中的锚点导航实现
在 Next.js 单页应用中,锚点导航可实现页面不同区域间的平滑切换,无需重新加载页面。react-use-observer-hooks 库中的 useAnchorObserver 钩子自动处理滚动与 URL 同步:它能在滚动时检测当前可见区域,并在地址变化时自动滚动至对应锚点。
该机制双向工作:滚动通过 IntersectionObserver 更新 URL,而 URL 变化(来自点击或后退按钮)则触发滚动至对应区域。这避免了反馈循环,并确保浏览器历史记录的正确处理。
项目设置
使用 Next.js 15(Pages Router)、React 19 和 Tailwind CSS v4。安装依赖:
npm install react-use-observer-hooks
在 next.config.ts 中禁用内置的滚动恢复功能,以避免与钩子冲突:
const nextConfig = {
experimental: {
scrollRestoration: false,
},
};
创建一个全捕获路由 [[...slug]].tsx,以在单页上处理类似 /、/about、/contact 的路径。
主页面代码
定义包含 href、标签和组件的区域数组:
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 根据可见区域自动高亮活动项。
应用行为
最终实现提供:
- 直接访问
/about等链接,准确跳转至对应区域。 - 正确的浏览器后退按钮功能。
- 搜索引擎索引支持,具有唯一 URL。
- 菜单与可见内容同步。
要点总结
useAnchorObserver钩子完全自动化双向滚动与 URL 同步。- 禁用
scrollRestoration至关重要,以避免冲突。 - Pages Router 中的全捕获路由适用于类 SPA 导航。
shallow: true+scroll: false最小化重新渲染。- 浏览器历史记录和 SEO 支持开箱即用。
— Editorial Team
暂无评论。