如何实现单页网站当前所在章节对应导航栏文本加粗效果
实现滚动时导航栏对应章节自动加粗高亮
核心思路
通过监听页面滚动事件,判断当前视口中的活跃章节,给导航栏对应项切换加粗样式,实现当前位置标识。
具体实现步骤
1. 确认章节组件的ID(确保已配置)
每个章节组件需带有唯一ID,比如:
// Home组件示例 function Home() { return <div id="home" className="section">首页内容</div>; }
其余组件依次对应:Purpose→id="purpose"、WhoWeAre→id="who-we-are"、FinancialSolutions→id="financial-solutions"、Products→id="products"、ComercialPartners→id="comercial-partners"、SocialMedia→id="social-media"。
2. 改造NavBar组件,实现滚动监听与高亮逻辑
在NavBar组件中加入状态管理和滚动监听,动态切换导航项样式:
import { useState, useEffect } from 'react'; function NavBar({ fixed }) { const [activeSection, setActiveSection] = useState('home'); // 滚动时判断活跃章节 const checkActiveSection = () => { const sections = document.querySelectorAll('.section'); const navHeight = document.querySelector('.navbar').clientHeight; sections.forEach(section => { const sectionTop = section.offsetTop; const sectionBottom = sectionTop + section.clientHeight; // 考虑导航栏高度偏移,避免遮挡时才触发高亮 if (window.scrollY >= sectionTop - navHeight && window.scrollY < sectionBottom - navHeight) { setActiveSection(section.id); } }); }; // 挂载/卸载时绑定/移除滚动监听 useEffect(() => { window.addEventListener('scroll', checkActiveSection); // 初始加载执行一次,确保默认高亮正确 checkActiveSection(); return () => window.removeEventListener('scroll', checkActiveSection); }, []); // 导航项配置 const navItems = [ { id: 'home', label: '首页' }, { id: 'purpose', label: '宗旨' }, { id: 'who-we-are', label: '关于我们' }, { id: 'financial-solutions', label: '金融解决方案' }, { id: 'products', label: '产品' }, { id: 'comercial-partners', label: '商业伙伴' }, { id: 'social-media', label: '社交媒体' }, ]; return ( <nav className={`navbar ${fixed ? 'fixed-top' : ''}`}> <ul> {navItems.map(item => ( <li key={item.id}> <a href={`#${item.id}`} // 通过内联样式控制加粗 style={{ fontWeight: activeSection === item.id ? 700 : 400 }} // 可选:添加平滑滚动 onClick={(e) => { e.preventDefault(); document.getElementById(item.id).scrollIntoView({ behavior: 'smooth' }); }} > {item.label} </a> </li> ))} </ul> </nav> ); } export default NavBar;
3. 优化与替代方案
- 性能优化:如果章节数量较多,可给滚动监听函数加节流,减少触发频率:
import { throttle } from 'lodash'; // 在useEffect中替换为节流后的函数 const throttledCheck = throttle(checkActiveSection, 100); useEffect(() => { window.addEventListener('scroll', throttledCheck); checkActiveSection(); return () => window.removeEventListener('scroll', throttledCheck); }, []); - CSS类替代内联样式:更推荐用CSS类控制样式,避免内联代码冗余:
然后修改JSX中的类名切换:/* 全局样式 */ .navbar a.active { font-weight: bold; }<a href={`#${item.id}`} className={activeSection === item.id ? 'active' : ''} // ...其他属性 > {item.label} </a>
内容的提问来源于stack exchange,提问作者Ruben Dario Guarnizo Martinez
相关产品推荐
相关产品推荐

