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

在Next.js项目中如何实现点击导航滚动到指定组件?

Next.js 同页滚动定位到组件实现方案

下面提供两种可直接落地的实现方式,可根据自己的需求选择:

方案1:原生锚点实现(零额外逻辑,改动最小)

适合不需要自定义滚动偏移、不需要特殊滚动回调的场景:

  • 给对应区块组件的最外层DOM添加唯一id,例如About区块加id="about",Services区块加id="services"
  • 修改Nav组件中Link的href属性,直接指向对应id的锚点即可:
<li className="nav-item">
  <Link href="#about">
    <a className="nav-link m-2 p-1 border border-dark pe-auto text-dark">About me</a>
  </Link>
</li>
<li className="nav-item">
  <Link href="#services"> 
    <a className="nav-link m-2 p-1 border border-dark  text-dark">Services</a>
  </Link>
</li>
  • 如需平滑滚动效果,在全局CSS中添加如下规则即可:
html {
  scroll-behavior: smooth;
}

如果是跨页面滚动定位,直接把href改成对应页面路由+锚点即可,比如/about#about,Next.js原生支持跳转后自动定位到对应锚点。

方案2:useRef跨组件传递实现(支持自定义滚动逻辑)

适合需要调整滚动偏移(比如fixed导航栏遮挡内容,要减去导航高度)、需要滚动完成后触发回调的场景:

步骤1:父组件定义ref和滚动方法,传递给子组件

修改Index.js代码:

import { useRef } from 'react'
import Nav from './Nav'
import Services from './Services'
import About from './About'

export default function Home () {
  const servicesRef = useRef(null)
  const aboutRef = useRef(null)

  const scrollToBlock = (targetRef) => {
    // 有fixed导航需要偏移的场景
    // window.scrollTo({
    //   top: targetRef.current.offsetTop - 80, // 80替换为你的导航栏实际高度
    //   behavior: 'smooth'
    // })
    // 不需要偏移直接用scrollIntoView即可
    targetRef.current?.scrollIntoView({
      behavior: 'smooth',
      block: 'start'
    })
  }

  return (
    <>
      <Nav scrollToBlock={scrollToBlock} aboutRef={aboutRef} servicesRef={servicesRef} />
      <About ref={aboutRef} />
      <Services ref={servicesRef} />
    </>
  )
}

步骤2:区块组件用forwardRef包裹接收ref

函数组件默认不支持直接接收ref,需要用forwardRef转发,以Services组件为例:

import { forwardRef } from 'react'

const Services = forwardRef((props, ref) => {
  return (
    <div ref={ref}>
      {/* 原Services组件的所有内容 */}
    </div>
  )
})

export default Services

步骤3:修改Nav组件调用滚动方法

function Nav ({ scrollToBlock, aboutRef, servicesRef }) {
  return (
    <div>
      <title>About</title>
      <ul className="nav justify-content-end m-1 p-1 col-12 pe-auto">
        <li className="nav-item">
          <a 
            className="nav-link m-2 p-1 border border-dark pe-auto text-dark"
            onClick={(e) => {
              e.preventDefault()
              scrollToBlock(aboutRef)
            }}
            href="#"
          >
            About me
          </a>
        </li>
        <li className="nav-item">
          <a 
            className="nav-link m-2 p-1 border border-dark text-dark"
            onClick={(e) => {
              e.preventDefault()
              scrollToBlock(servicesRef)
            }}
            href="#"
          >
            Services
          </a>
        </li>
      </ul>
    </div>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:24:02