Bootstrap5 Popover内置关闭按钮、点击空白关闭实现方案
实现Bootstrap 5 Popover两个交互需求
需求说明
需要实现两个Popover交互逻辑:
- 点击弹出框
data-bs-content配置项内部的关闭按钮时,关闭当前Popover - 点击页面body空白区域时,自动关闭所有已打开的Popover
问题根因
之前直接用$(this).closest(".popover").hide()手动隐藏DOM元素的写法,不会同步Bootstrap Popover组件的内部状态,组件会判定Popover仍处于展示状态,导致关闭后无法再次点击触发打开。
完整实现代码
HTML部分(原有写法无需修改)
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script> <a href="javascript:void(0)" class="btn btn-primary ripple-effect m-4" data-bs-toggle="popover" data-bs-html="true" data-bs-placement="left" data-bs-content="<a href='javascript:void(0)' class='d-flex justify-content-end close-popover' aria-label='Close'><div class='icon icon-16 icon-lg-16 mb-2'>X</div></a><div class='sec-paragraph'><div class='p4'><p>Lorem ipsum dolor sit amet, consectetur apising elit, sed do eiusmod tempor incididut ut labore et dolore magna aliqua. Ut enim ad minim.</p></div> </div>">Popover(White) left with close btn</a>
JS部分
$(document).ready(function() { // 初始化所有Popover组件 const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl) }) // 功能1:点击Popover内部关闭按钮,关闭当前Popover $(document).on("click", ".popover .close-popover" , function(){ const $currentPopover = $(this).closest('.popover') const popoverId = $currentPopover.attr('id') // 通过Bootstrap自动生成的aria-describedby属性匹配对应触发按钮 const $triggerEl = $(`[aria-describedby="${popoverId}"]`) const popoverInstance = bootstrap.Popover.getInstance($triggerEl[0]) // 调用官方提供的hide方法,不要直接修改DOM样式 popoverInstance.hide() }); // 功能2:点击页面空白区域关闭所有已打开的Popover $(document).on('click', function(e) { const clickTarget = $(e.target) // 点击触发按钮、Popover内部内容时不执行关闭 if (clickTarget.closest('[data-bs-toggle="popover"]').length || clickTarget.closest('.popover').length) { return } // 遍历所有Popover实例,隐藏处于展示状态的弹窗 popoverTriggerList.forEach(triggerEl => { const instance = bootstrap.Popover.getInstance(triggerEl) if (instance._isShown()) { instance.hide() } }) }) });
关键注意点
- 所有关闭操作必须调用Popover实例提供的官方
hide()方法,禁止直接操作DOM修改display属性隐藏元素,否则会出现组件状态不同步、无法二次打开的问题 - Popover内容是动态插入到页面的,绑定关闭按钮事件必须用事件委托的写法,否则会因为元素初始不存在导致绑定失效
- 点击外部关闭的逻辑需要过滤掉触发按钮和Popover内部的点击事件,避免正常点击触发按钮、操作Popover内容时被误关闭
内容的提问来源于stack exchange,提问作者Awais
相关产品推荐
相关产品推荐

