Accordion菜单JavaScript报错排查与功能修复求助
解决Accordion菜单的TypeError: Cannot read properties of undefined (reading 'toggle')问题
问题根源
- 箭头函数的
this绑定错误:你用箭头函数作为点击事件处理函数,箭头函数不会创建独立的this上下文,会继承外层作用域的this。这里外层是全局作用域,this指向undefined(严格模式下),调用this.classList.toggle自然会抛出TypeError。 - 错误操作CSS伪类:
this.classList.toggle("accordion_btn:hover")完全无效,:hover是CSS伪类,不属于元素的类名集合,无法通过classList来切换。
修复方案
1. 替换箭头函数为普通函数
普通函数作为事件处理函数时,this会自动绑定到触发事件的DOM元素(即点击的按钮)。
2. 移除伪类切换逻辑,用CSS规则实现状态变化
通过CSS优先级,让.active类的样式覆盖默认或hover状态的样式,或者单独定义.accordion_btn.active:hover的样式。
3. 用CSS类控制面板显示(更易维护)
替代直接修改style.display,通过切换类来控制面板的显示/隐藏,符合样式与逻辑分离的原则。
修复后的完整代码
JavaScript
const acc = document.getElementsByClassName("accordion_btn"); for (let i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function() { // 切换按钮的active类 this.classList.toggle("active"); // 获取对应面板并切换显示类 const panel = this.nextElementSibling; panel.classList.toggle("show"); }); }
CSS
.accordion_btn { width: 100%; background-color: hsl(0, 0%, 100%); text-align: left; border: none; outline: none; margin: 20px 0; transition: 0.4s; } .accordion_btn:hover { background-color: hsl(276, 51%, 90%); } /* active状态样式,覆盖默认样式 */ .accordion_btn.active { background-color: red; } /* active状态下的hover样式(可选) */ .accordion_btn.active:hover { background-color: darkred; } .panel { font-weight: 400; color: hsl(292, 16%, 49%); display: none; overflow: hidden; margin-bottom: 20px; text-align: left; } /* 用类控制面板显示 */ .panel.show { display: block; }
HTML
<div class="accordion"> <button class="accordion_btn"> What is Frontend Mentor, and how will it help me? </button> <div class="panel"> <p> Frontend Mentor offers...</p> </div> </div> <div class="accordion"> <button class="accordion_btn"> Is Frontend Mentor free? </button> <div class="panel"> <p>Yes, Frontend Mentor...</p> </div> </div> <div class="accordion"> <button class="accordion_btn"> Can I use Frontend Mentor projects in my portfolio? </button> <div class="panel"> <p>Yes...</p> </div> </div> <div class="accordion"> <button class="accordion_btn"> How can I get help if I'm stuck on a Frontend Mentor challenge? </button> <div class="panel"> <p>The best place to...</p> </div> </div>
额外说明
如果坚持要用箭头函数,可以通过event.currentTarget获取触发事件的按钮元素替代this:
acc[i].addEventListener("click", (event) => { const btn = event.currentTarget; btn.classList.toggle("active"); const panel = btn.nextElementSibling; panel.classList.toggle("show"); });
内容的提问来源于stack exchange,提问作者Adritriz
相关产品推荐
相关产品推荐

