使用原生JavaScript实现多级嵌套动态高度手风琴的问题求助
问题根因
- 事件绑定的元素选择器错误,未匹配到实际可点击的触发节点
- 嵌套层级展开时,父容器的固定max-height不会随子内容高度变化更新,会导致子内容展开后被截断
- 子层级触发元素是a标签,未阻止默认跳转行为,会干扰交互
修复后完整代码
CSS
.drop-down-menu, .sub-ul-2-a{ max-height: 0px; overflow: hidden; transition: max-height 350ms ease-in-out; } /* 新增:给可点击元素加手势提示 */ .first-ul-1 > li > p, .sub-ul-1-a > li > a { cursor: pointer; }
JavaScript
window.addEventListener("DOMContentLoaded", () => { // 正确匹配所有可点击的手风琴触发元素 const triggers = document.querySelectorAll('.first-ul-1 > li > p, .sub-ul-1-a > li > a'); triggers.forEach(trigger => { trigger.addEventListener('click', openAccordion); }); // 递归更新所有父级展开容器的高度 function updateParentHeight(el) { const parentWrap = el.closest('.drop-down-menu, .sub-ul-2-a'); if (parentWrap && parentWrap.style.maxHeight !== '0px') { parentWrap.style.maxHeight = parentWrap.scrollHeight + 'px'; updateParentHeight(parentWrap); } } function openAccordion(e) { // 阻止a标签默认跳转行为 e.preventDefault(); const content = this.nextElementSibling; // 没有对应展开内容直接返回 if (!content || !['drop-down-menu', 'sub-ul-2-a'].some(cls => content.classList.contains(cls))) return; const parentLi = this.parentElement; if (!parentLi.classList.contains('open')) { parentLi.classList.add('open'); content.style.maxHeight = content.scrollHeight + 'px'; // 子内容展开后更新所有父级容器高度 updateParentHeight(content); } else { parentLi.classList.remove('open'); content.style.maxHeight = '0px'; // 收起后也更新父级容器高度 updateParentHeight(content); } } });
HTML
不需要修改原有结构,直接复用你现有代码即可。
实现说明
- 修正了触发元素的选择器,分别匹配一级分类的p标签、二级分类的a标签作为点击触发节点
- 新增了父级高度递归更新逻辑,子分类展开/收起时会同步更新所有上层展开容器的max-height,避免内容被截断
- 新增a标签默认行为阻止,避免点击子分类触发页面跳转
- 保留了原本的max-height过渡动画逻辑,完全用原生JS实现,无第三方依赖
内容的提问来源于stack exchange,提问作者Script Host
相关产品推荐
相关产品推荐

