不刷新页面修改标签类属性并应用样式:导航菜单Active状态实现问题及解决
导航菜单点击高亮的原生JavaScript问题解决
问题背景
我尝试优化导航菜单栏的布局,需求很明确:点击菜单项时,给当前点击的项添加active类(让它高亮为蓝色),其余未选中的项保持inactive类(灰色)。我用原生JavaScript写了makeActive()函数,通过onclick事件调用,但样式始终没变化,当前激活项的布局完全没反应,一开始还以为是DOM或者AJAX的问题,折腾半天终于找到根源了。
原始代码
styles.css
/* NavBar */ .topnav { background-color: #333; overflow: hidden; margin: 0; font-family: Arial, Helvetica, sans-serif; } .topnav a { float: left; color: #f2f2f2; text-decoration: none; text-align: center; padding: 8px 16px; font-size: 17px; } .topnav a.active { background-color: rgb(49, 149, 250); color: white; } .topnav a:hover { background-color: #ddd; color: black; }
index.html
<!DOCTYPE html> <html> <head> <title>Travel Agency</title> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="styles.css"> <script> function makeActive(id) { var ancestor = document.getElementsByClassName('topnav'); var descendents = ancestor[0].getElementsByTagName('*'); for(var i = 0; i < descendents.length; i++) { if (descendents[i].className === "active" && descendents[i].id != id) { descendents[i].className = "inactive"; break; } } for(var i = 0; i < descendents.length; i++) { if (descendents[i].id = id) { descendents[i].className = "active"; break; } } } </script> </head> <body> <div class="topnav"> <a class="active" id="home" href="#home" onclick="makeActive('home')">Home</a> <a class="inactive" id="offers" href="#offers" onclick="makeActive('offers')">Offers</a> <a class="inactive" id="travels" href="#travels" onclick="makeActive('travels')">Travels</a> <a class="inactive" id="galery" href="#galery" onclick="makeActive('galery')">Galery</a> <a class="inactive" id="contact" href="#contact" onclick="makeActive('contact')">Contact</a> <a class="inactive" id="about" href="#about" onclick="makeActive('about')">About</a> </div> </body> </html>
问题排查与解决
问题其实非常隐蔽——在makeActive函数的第二个for循环里,我把全等比较运算符===误写成了赋值运算符=。
错误代码行:
if (descendents[i].id = id)
这行代码不是在判断元素的id是否等于传入的参数,而是在给descendents[i].id赋值,导致逻辑完全走偏,根本找不到要设置active类的目标元素,样式自然不会生效。修正后的
makeActive函数:
function makeActive(id) { var ancestor = document.getElementsByClassName('topnav'); var descendents = ancestor[0].getElementsByTagName('*'); for(var i = 0; i < descendents.length; i++) { if (descendents[i].className === "active" && descendents[i].id != id) { descendents[i].className = "inactive"; break; } } for(var i = 0; i < descendents.length; i++) { if (descendents[i].id === id) { // 修正为全等比较 descendents[i].className = "active"; break; } } }
修正之后,点击菜单项就能正常切换active和inactive类,高亮效果也能正确显示了。
额外优化建议
如果想让代码更简洁高效,可以简化DOM操作,不用遍历所有后代元素:
function makeActive(id) { // 直接获取所有导航链接 const navLinks = document.querySelectorAll('.topnav a'); // 先把所有链接统一设置为inactive navLinks.forEach(link => link.className = 'inactive'); // 找到当前点击的链接,设置为active const targetLink = document.getElementById(id); if (targetLink) targetLink.className = 'active'; }
这种写法逻辑更清晰,也避免了不必要的DOM遍历,性能更好。
内容的提问来源于stack exchange,提问作者kirsten992
相关产品推荐
相关产品推荐

