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

React.js中滚动到对应区域时高亮菜单项的实现求助

实现滚动时导航菜单项高亮的方案

嗨,这个需求其实挺常见的,我来给你一步步拆解实现方法,保证易懂好上手~

第一步:核心逻辑梳理

要实现滚动时对应导航项高亮,核心就是两个关键点:

  • 判断当前页面滚动到了哪个区域
  • 给对应区域的导航项加上高亮样式

第二步:HTML结构准备

首先确保你的导航链接和页面区域是一一对应的,用id关联起来:

<!-- 导航栏 -->
<nav class="navbar">
  <ul>
    <li><a href="#home" class="nav-link">Home</a></li>
    <li><a href="#about" class="nav-link">About</a></li>
    <li><a href="#services" class="nav-link">Services</a></li>
    <li><a href="#contact" class="nav-link">Contact</a></li>
  </ul>
</nav>

<!-- 页面区域 -->
<section id="home" class="section">Home 区域</section>
<section id="about" class="section">About 区域</section>
<section id="services" class="section">Services 区域</section>
<section id="contact" class="section">Contact 区域</section>

第三步:CSS样式配置

先写好导航的基础样式,再定义高亮的active类(也就是你要的红色效果):

/* 导航栏固定在顶部 */
.navbar {
  position: fixed;
  top: 0;
  width: 100%;
  background: #fff;
  padding: 1rem;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.navbar ul {
  list-style: none;
  display: flex;
  gap: 2rem;
  justify-content: center;
  margin: 0;
  padding: 0;
}

/* 导航链接默认样式 */
.nav-link {
  text-decoration: none;
  color: #333;
  font-size: 1.1rem;
  transition: color 0.3s ease;
}

/* 高亮样式(红色) */
.nav-link.active {
  color: red;
  font-weight: bold;
}

/* 让每个区域占满视口,方便测试滚动 */
.section {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
}

/* 给不同区域加背景色区分 */
#home { background: #f5f5f5; }
#about { background: #eee; }
#services { background: #e5e5e5; }
#contact { background: #ddd; }

第四步:JavaScript核心逻辑

这部分是实现功能的关键,我们要监听滚动事件,判断当前激活的区域,然后给对应导航项加高亮:

// 获取所有导航链接和页面区域
const navLinks = document.querySelectorAll('.nav-link');
const sections = document.querySelectorAll('.section');

// 防抖函数(优化滚动性能,避免频繁触发事件)
function debounce(func, delay = 100) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => func.apply(this, arguments), delay);
  };
}

// 滚动事件处理函数
function handleScroll() {
  let currentSectionId = '';

  // 遍历每个区域,判断是否处于当前视口的激活范围
  sections.forEach(section => {
    const sectionTop = section.offsetTop; // 区域顶部到页面顶部的距离
    const sectionHeight = section.clientHeight; // 区域自身高度

    // 当滚动距离 >= 区域顶部 - 100px(这个值可以根据你的导航栏高度调整)
    // 提前触发高亮,体验更自然
    if (window.pageYOffset >= sectionTop - 100) {
      currentSectionId = section.getAttribute('id');
    }
  });

  // 更新导航链接的高亮状态
  navLinks.forEach(link => {
    link.classList.remove('active');
    // 找到对应区域的导航链接,添加active类
    if (link.getAttribute('href') === `#${currentSectionId}`) {
      link.classList.add('active');
    }
  });
}

// 监听滚动事件(用防抖包装)
window.addEventListener('scroll', debounce(handleScroll));

// 页面加载完成后,触发一次滚动,初始化高亮状态
window.addEventListener('load', () => {
  window.dispatchEvent(new Event('scroll'));
});

关键细节说明

  1. 触发时机调整:代码里的sectionTop - 100是为了让高亮提前触发,比如你的导航栏高度是80px,就改成sectionTop - 80,这样当区域顶部刚好到导航栏下方时就高亮,体验更流畅。
  2. 防抖优化:滚动事件会频繁触发,用防抖函数可以减少函数执行次数,避免页面卡顿,提升性能。
  3. 初始高亮:页面加载时触发一次滚动事件,确保刷新页面后,当前所在区域的导航项也能正确高亮。

这样一来,不管是点击导航滚动到对应区域,还是手动滚动页面,对应的导航项都会自动变成红色高亮啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:17:03