如何实现Accordion悬停预览内容、点击后保持展开?
提问内容
- 问题截图
- 开发诉求:为手风琴组件实现悬停预览内容的效果,要求用户点击组件标题后,对应内容块可以保持展开状态
- 附演示项目代码地址:https://codepen.io/sarah-omelia/pen/QWdYXMy
用户提交的原始代码
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <h2>Accordion with symbols</h2> <p>In this example we have added a "plus" sign to each button. When the user clicks on the button, the "plus" sign is replaced with a "minus" sign.</p> <div> <button id="acchead" class="accordion">Section 1</button> <div class="accordion-body"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <button id="acchead" class="accordion">Section 2</button> <div class="accordion-body"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> <button id="acchead" class="accordion">Section 3</button> <div class="accordion-body"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> </div> </div>
代码内英文内容释义:
- 二级标题:带符号标识的手风琴组件
- 正文说明:本示例为每个按钮添加了加号标识,用户点击按钮后,加号会切换为减号
- 区块标题:第一区块、第二区块、第三区块
问题定位
- 三个按钮重复使用同一个
id="acchead",违反HTML id全局唯一的规范,会导致DOM选择器匹配异常 - 缺少状态区分逻辑,无法区分“鼠标悬停临时预览”和“用户主动点击锁定展开”两种交互场景,默认的鼠标移出收起逻辑会覆盖点击后的保持展开状态
实现方案
- 移除重复的id属性,统一通过
accordion类选择器绑定事件 - 为每个手风琴区块增加锁定状态标记,交互逻辑如下:
- 鼠标悬停在未锁定的手风琴标题上时,临时展开对应内容块
- 鼠标移出未锁定的手风琴标题时,收起临时展开的内容块
- 点击手风琴标题时,切换对应区块的锁定状态;锁定后无论鼠标悬停还是移出,内容块都会保持展开
- 补充对应CSS样式,区分默认、悬停预览、点击锁定三种状态下的符号标识
核心交互逻辑参考代码:
document.querySelectorAll('.accordion').forEach(btn => { const content = btn.nextElementSibling let isLocked = false // 初始为未锁定状态 // 悬停时,仅在未锁定状态下临时展开 btn.addEventListener('mouseenter', () => { if (!isLocked) content.classList.add('active') }) // 移出时,仅在未锁定状态下收起内容 btn.addEventListener('mouseleave', () => { if (!isLocked) content.classList.remove('active') }) // 点击时切换锁定状态 btn.addEventListener('click', () => { isLocked = !isLocked content.classList.toggle('active', isLocked) }) })
内容的提问来源于stack exchange,提问作者Sarah O'Melia
相关产品推荐
相关产品推荐

