侧边栏菜单项点击切换is-active类实现选中变色问题排查
问题排查
你的代码一共有3个核心错误,直接导致功能失效:
document.getElementsByClassName("menu-item")返回值是 HTMLCollection 类型的类数组结构,不是标准数组,本身没有map方法,直接调用会抛出类型错误;而且map方法的设计目的是生成遍历后的新数组,根本不适合做批量修改DOM类名的副作用操作。- 内联事件写
onclick="changeColor()"时,函数执行的上下文是全局window,不是当前点击的DOM元素,所以函数里的this指向window,访问this.classList会直接报找不到属性的错误。 links.map(classList.remove("is-active"))本身语法逻辑错误,既没有给map传入合法的遍历回调函数,也没有指定要操作哪个DOM元素的classList,代码执行到这一步就会中断。
修正代码
你的CSS样式部分没有问题,只需要修改HTML和JS逻辑即可,这里给两种可用方案:
方案1:保留内联事件写法(最小改动)
首先修改HTML里的事件绑定,把当前点击元素作为参数传入函数:
<aside id="side-bar" class="sidebar"> <h3>Pages</h3> <nav class="menu"> <a onclick="changeColor(this)" class="menu-item is-active">page 1</a> <a onclick="changeColor(this)" class="menu-item">page 2</a> <a onclick="changeColor(this)" class="menu-item">page 3</a> </nav> </aside>
然后重写changeColor函数,用循环遍历所有菜单项移除激活类,再给传入的当前元素加类:
function changeColor(currentItem){ const links = document.getElementsByClassName("menu-item") // 遍历所有菜单项,移除已有的激活样式 for (const item of links) { item.classList.remove("is-active") } // 给当前点击项添加激活样式 currentItem.classList.add("is-active") }
方案2:事件委托写法(推荐,更易维护)
不建议在每个DOM元素上写重复的内联事件,直接给父级菜单绑定一次点击事件即可,后续新增菜单项也不需要额外绑定事件,HTML更干净:
首先删掉所有a标签上的onclick属性:
<aside id="side-bar" class="sidebar"> <h3>Pages</h3> <nav class="menu"> <a class="menu-item is-active">page 1</a> <a class="menu-item">page 2</a> <a class="menu-item">page 3</a> </nav> </aside>
JS逻辑改为事件委托实现:
document.addEventListener('DOMContentLoaded', () => { const menu = document.querySelector('.menu') // 用querySelectorAll直接返回可遍历的NodeList const menuItems = document.querySelectorAll('.menu-item') menu.addEventListener('click', (e) => { // 只处理点击菜单项的情况 if (!e.target.classList.contains('menu-item')) return // 批量移除所有激活类 menuItems.forEach(item => item.classList.remove('is-active')) // 给当前点击项加激活类 e.target.classList.add('is-active') }) })
内容的提问来源于stack exchange,提问作者Cristian Anton
相关产品推荐
相关产品推荐

