如何根据最后点击的项修改导航栏元素的底部边框样式?
导航栏选中状态修复方案
问题根源
每个NavButton子组件都维护着独立的selectedNavButton状态,彼此完全隔离。点击其中一个按钮时,只有该组件自身的状态会更新,其他按钮无法感知当前选中的是哪一项,导致无法实现「仅最后点击的选项显示底部边框」的需求。另外,setState是异步操作,你在handleNavButtonClick里立刻打印selectedNavButton得到的会是旧值,不过这不是核心问题。
修正方案:状态提升到父组件
把选中状态移到父组件Navbar中统一管理,所有子组件共享同一个状态源,这样就能确保只有最后点击的项被标记为选中。
修改后的父组件Navbar
const Navbar = () => { // 父组件统一维护选中的导航项 const [selectedNav, setSelectedNav] = useState(""); const handleNavClick = (navText) => { setSelectedNav(navText); }; return ( <nav className='navbar'> <motion.a className='logo' {...slideAnimation('left')}> some text </motion.a> <NavButton textNavButton={"_hello"} isSelected={selectedNav === "_hello"} onClick={() => handleNavClick("_hello")} /> <NavButton textNavButton={"_about-me"} isSelected={selectedNav === "_about-me"} onClick={() => handleNavClick("_about-me")} /> </nav> ); }
修改后的子组件NavButton
const NavButton = ({textNavButton, isSelected, onClick}) => { // 子组件不再维护状态,仅接收父组件传递的状态和点击事件 return ( <div> <a className={`${isSelected ? "selectedLink" : "links"}`} onClick={onClick} > {textNavButton} </a> </div> ) }
优化CSS(可选)
可以减少重复样式,只保留差异部分:
.links{ color:white; border-right: 1px solid rgb(73, 73, 73); padding: 20px 30px; font-size: 13px; } .selectedLink{ composes: links; /* 继承links的所有样式 */ border-bottom: 2px solid #d6b600; } /* 如果你的环境不支持`composes`,就写完整样式: .selectedLink{ color:white; border-right: 1px solid rgb(73, 73, 73); padding: 20px 30px; font-size: 13px; border-bottom: 2px solid #d6b600; } */
进阶优化:循环渲染导航项
如果后续需要添加更多导航项,可以把导航数据抽成数组,通过循环渲染减少重复代码:
const Navbar = () => { const [selectedNav, setSelectedNav] = useState(""); // 导航项数据集合 const navItems = ["_hello", "_about-me"]; const handleNavClick = (navText) => { setSelectedNav(navText); }; return ( <nav className='navbar'> <motion.a className='logo' {...slideAnimation('left')}> some text </motion.a> {navItems.map(item => ( <NavButton key={item} textNavButton={item} isSelected={selectedNav === item} onClick={() => handleNavClick(item)} /> ))} </nav> ); }
这样后续新增导航项,只需要在navItems数组里添加元素即可,无需重复编写NavButton代码。
内容的提问来源于stack exchange,提问作者Bigbool98
相关产品推荐
相关产品推荐

