如何实现daisyUI中details summary下拉菜单的自动关闭功能?
基于daisyUI的details/summary实现互斥折叠+点击外部关闭的下拉菜单
要实现你需求的两个效果(互斥展开、点击外部关闭),只需要添加一段JavaScript逻辑即可,分两部分处理:
1. 互斥展开逻辑
给所有details元素绑定点击事件,当点击某个菜单的summary展开时,自动关闭其他所有已展开的details:
- 只监听
summary的点击(避免点击下拉菜单内的链接误触发) - 如果当前菜单本身是展开状态,点击后会自动关闭,不需要处理其他菜单
2. 点击外部关闭逻辑
监听文档的全局点击事件,判断点击位置是否在任意一个下拉菜单内部:
- 如果点击位置不在菜单内,就关闭所有处于展开状态的
details
完整代码
<link href="https://cdnjs.cloudflare.com/ajax/libs/daisyui/3.5.0/full.min.css" rel="stylesheet" type="text/css" /> <script src="https://cdn.tailwindcss.com"></script> <div class="flex-1"> <ul class="menu menu-horizontal px-1"> <li><a>Dashboard</a></li> <li> <details> <summary>Master Data</summary> <ul class="p-2 bg-base-100"> <li><a>Link 1</a></li> <li><a>Link 2</a></li> </ul> </details> </li> <li> <details> <summary>Stocks</summary> <ul class="p-2 bg-base-100"> <li><a>Link 1</a></li> <li><a>Link 2</a></li> </ul> </details> </li> </ul> </div> <script> // 获取所有下拉菜单的details元素 const dropdownDetails = document.querySelectorAll('details'); // 绑定互斥展开事件 dropdownDetails.forEach(detail => { detail.addEventListener('click', (e) => { // 仅当点击summary时触发逻辑 if (!e.target.closest('summary')) return; // 如果当前菜单已经展开,点击后会自动关闭,无需处理其他菜单 if (detail.open) return; // 关闭其他所有展开的菜单 dropdownDetails.forEach(otherDetail => { if (otherDetail !== detail) { otherDetail.removeAttribute('open'); } }); }); }); // 绑定点击外部关闭事件 document.addEventListener('click', (e) => { // 判断点击是否在任意一个下拉菜单内部 const isInsideDropdown = [...dropdownDetails].some(detail => detail.contains(e.target)); if (!isInsideDropdown) { // 点击外部,关闭所有展开的菜单 dropdownDetails.forEach(detail => detail.removeAttribute('open')); } }); </script>
关键说明
- 保留了daisyUI自带的
summary图标切换效果,无需额外修改样式 - 逻辑中加入了子元素判断,避免点击下拉菜单内的链接时误触发菜单关闭/切换
- 完全基于原生JavaScript实现,不需要额外依赖
内容的提问来源于stack exchange,提问作者d41d8cd98f00b204e9800998ecf842
相关产品推荐
相关产品推荐

