Accordion复制文本触发关闭及点击外部自动关闭问题求解
Accordion组件问题解决方案
问题1:复制文本时触发Accordion关闭
解决思路
原代码将点击事件绑定在整个.content-container上,导致用户复制文本时的鼠标操作会误触折叠逻辑。我们可以将点击事件仅绑定到.question元素,只有点击问题标题才切换面板状态,避免内容区域的操作触发折叠。
修改后的核心JS逻辑
const accordionPanels = document.querySelectorAll(".content-container"); const questions = document.querySelectorAll(".question"); questions.forEach(question => { question.addEventListener("click", function() { const panel = this.parentElement; const isActive = panel.classList.contains("active"); // 先关闭所有面板 accordionPanels.forEach(p => p.classList.remove("active")); // 当前面板未激活则打开它 if (!isActive) { panel.classList.add("active"); } }); });
问题2:点击外部区域自动关闭Accordion
解决思路
给window添加点击事件监听,通过Element.contains()方法判断点击目标是否在Accordion内部。如果点击的是外部区域,则移除所有面板的active类,实现自动关闭。
补充代码(添加到JS末尾)
window.addEventListener("click", function(e) { const accordion = document.querySelector(".accordion"); // 判断点击目标是否不属于Accordion内部元素 if (!accordion.contains(e.target)) { accordionPanels.forEach(panel => panel.classList.remove("active")); } });
完整修改后的JS代码
const accordionPanels = document.querySelectorAll(".content-container"); const questions = document.querySelectorAll(".question"); // 绑定问题标题的点击切换逻辑 questions.forEach(question => { question.addEventListener("click", function() { const panel = this.parentElement; const isActive = panel.classList.contains("active"); accordionPanels.forEach(p => p.classList.remove("active")); if (!isActive) { panel.classList.add("active"); } }); }); // 点击外部区域关闭所有面板 window.addEventListener("click", function(e) { const accordion = document.querySelector(".accordion"); if (!accordion.contains(e.target)) { accordionPanels.forEach(panel => panel.classList.remove("active")); } });
原HTML与SCSS代码(无需修改)
HTML
<div class="accordion"> <h2 class="accordion-title">Frequently asked questions</h2> <div class="content-container active"> <div class="question">What is the return Policy</div> <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div> </div> <div class="content-container"> <div class="question">Where can you find us</div> <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div> </div> <div class="content-container"> <div class="question">Some other text</div> <div class="answer">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Incidunt dolores non eaque beatae dolor veniam amet, molestiae neque quibusdam ipsa!</div> </div> </div>
SCSS
.accordion{ margin: 0 auto; width: 60%; border-color: #fff; padding: 2rem; border-radius: 30px; &-title{ margin-bottom: 2rem; text-align: center; } .content-container .question{ padding: 1rem 0; font-size: 22px; cursor: pointer; border-bottom: 1px solid #000; position: relative; &::after{ content: "+"; position: absolute; right: -5px; } } .answer{ padding-top: 1rem; font-size: 22px; line-height: 1.5; width: 100%; height: 0px; overflow: hidden; transition: all .5s; } } // js styling link .accordion .content-container.active{ .question{ &::after{ content: "-"; font-size: 2rem; transition: .5s; } } .answer{ height: 150px; } }
内容的提问来源于stack exchange,提问作者Filip Drábek
相关产品推荐
相关产品推荐

