ReactJS滚动高亮激活导航菜单及导航空间不足展示方案咨询
React 移动端导航栏(滚动高亮+溢出滚动)完整实现方案
1. 页面滚动时高亮当前激活导航菜单的实现
- 首先给每个导航菜单对应的页面区块设置唯一的
id属性,比如菜品分类对应#recommend、#hot等 - 监听
window的scroll事件,增加节流优化避免频繁触发回调,计算每个区块距离视口顶部的距离getBoundingClientRect().top - 当某个区块的
top值小于等于导航栏的高度(可额外加10-20px偏移量避免判定误差),且区块底部距离视口顶部的距离大于导航栏高度时,就把当前区块对应的导航项设为激活状态 - 激活状态通过自定义类名修改文字颜色、底部下划线等样式实现,同时支持点击导航项平滑滚动到对应区块
核心实现代码如下:
import { useState, useEffect, useCallback } from 'react'; // 导航菜单配置,可根据业务需求修改 const navList = [ { id: 'recommend', name: '推荐' }, { id: 'hot', name: '热销' }, { id: 'drink', name: '饮品' }, { id: 'snack', name: '小吃' }, { id: 'main', name: '主食' }, { id: 'dessert', name: '甜点' } ]; const NavBar = () => { const [activeId, setActiveId] = useState('recommend'); const NAV_HEIGHT = 50; // 导航栏固定高度,可根据实际样式调整 // 节流函数,控制滚动事件触发频率 const throttle = (func, delay) => { let timer = null; return function(...args) { if (!timer) { timer = setTimeout(() => { func.apply(this, args); timer = null; }, delay); } } }; // 滚动监听逻辑,判定当前激活区块 const handleScroll = useCallback(throttle(() => { for (const item of navList) { const element = document.getElementById(item.id); if (!element) continue; const rect = element.getBoundingClientRect(); if (rect.top <= NAV_HEIGHT && rect.bottom > NAV_HEIGHT) { setActiveId(item.id); break; } } }, 100), []); useEffect(() => { window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, [handleScroll]); // 点击导航项平滑滚动到对应区块 const scrollToSection = (id) => { const element = document.getElementById(id); if (element) { const offsetTop = element.offsetTop - NAV_HEIGHT; // 减去导航高度避免内容被遮挡 window.scrollTo({ top: offsetTop, behavior: 'smooth' }); } }; // 激活项自动滚动到导航栏可视区域 useEffect(() => { const activeNav = document.querySelector(`.nav-item[data-id="${activeId}"]`); if (activeNav) { activeNav.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } }, [activeId]); return ( <nav className="nav-container"> {navList.map(item => ( <div key={item.id} data-id={item.id} className={`nav-item ${activeId === item.id ? 'active' : ''}`} onClick={() => scrollToSection(item.id)} > {item.name} </div> ))} </nav> ) }; export default NavBar;
2. 导航区域空间不足时完整展示所有选项的实现
核心通过CSS实现横向滚动效果,无需折叠为汉堡菜单,样式代码如下:
.nav-container { position: sticky; top: 0; height: 50px; z-index: 99; background: #fff; display: flex; /* 核心横向滚动配置 */ overflow-x: auto; white-space: nowrap; /* 隐藏滚动条,兼容多浏览器 */ -ms-overflow-style: none; scrollbar-width: none; } /* 隐藏Chrome/Safari等webkit内核浏览器的滚动条 */ .nav-container::-webkit-scrollbar { display: none; } .nav-item { padding: 0 16px; line-height: 50px; font-size: 14px; color: #333; flex-shrink: 0; /* 避免导航项被压缩 */ cursor: pointer; position: relative; } .nav-item.active { color: #ff4d4f; font-weight: 500; } /* 激活项底部下划线 */ .nav-item.active::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 20px; height: 2px; background: #ff4d4f; }
内容的提问来源于stack exchange,提问作者Emtiaz Pias
相关产品推荐
相关产品推荐

