使用popper.js实现打开新popover时自动关闭其余已打开popover的问题求助
问题修复方案
HTML修改
给所有popover弹窗元素统一添加popover-content类名,方便全局选择控制,修改后示例如下,剩余两个弹窗同理添加该类即可:
<div class="hidden popover-content bg-white border mr-3 block z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg" id="popover-cv-bottom">
JS代码替换
把原有JS逻辑替换为以下代码:
// 存储popper实例避免重复创建,减少内存占用 const popperInstances = new Map(); function openPopover(event, tooltipID, position) { // 直接获取绑定事件的按钮元素,无需遍历父节点 const triggerBtn = event.currentTarget; const currentPopover = document.getElementById(tooltipID); // 关闭所有非当前的已打开popover document.querySelectorAll('.popover-content').forEach(pop => { if (pop.id !== tooltipID && !pop.classList.contains('hidden')) { pop.classList.add('hidden'); // 销毁无用的popper实例 if (popperInstances.has(pop.id)) { popperInstances.get(pop.id).destroy(); popperInstances.delete(pop.id); } } }); // 切换当前popover显隐状态 const willShow = currentPopover.classList.contains('hidden'); if (willShow) { // 仅在打开时创建popper实例 const popper = Popper.createPopper(triggerBtn, currentPopover, { placement: position }); popperInstances.set(tooltipID, popper); currentPopover.classList.remove('hidden'); } else { currentPopover.classList.add('hidden'); if (popperInstances.has(tooltipID)) { popperInstances.get(tooltipID).destroy(); popperInstances.delete(tooltipID); } } event.stopPropagation(); } // 可选功能:点击页面空白区域关闭所有popover document.addEventListener('click', () => { document.querySelectorAll('.popover-content').forEach(pop => { if (!pop.classList.contains('hidden')) { pop.classList.add('hidden'); if (popperInstances.has(pop.id)) { popperInstances.get(pop.id).destroy(); popperInstances.delete(pop.id); } } }); });
修复说明
- 自动关闭其他popover:每次触发点击时先遍历所有弹窗,关闭除当前操作外的所有已打开弹窗,实现单例打开效果
- event废弃警告修复:使用
event.currentTarget直接获取绑定事件的按钮,替代原有event.target向上遍历父节点的逻辑,避免了不符合规范的event对象使用方式,消除废弃警告 - 额外优化:统一管理popper实例,避免重复创建实例导致的内存泄漏和性能问题
内容的提问来源于stack exchange,提问作者R-b-n
相关产品推荐
相关产品推荐

