Bootstrap Popover首次触发后无法再次弹出的问题求助
问题描述
我初步调研后确认这是真实存在的问题,但还没确定解决方案。
复现步骤
- 在第一个输入框输入“0”
- 接下来两个输入框都输入“2”(或任意相同数字)
- 点击按钮,会弹出提示为“你选择了0,该值不能为0”的气泡弹窗(popover)
- 将
input-a中的“0”改为任意非零数字 - 再次点击按钮——此时无任何反应
预期行为:触发下一个if语句,提示b和c不能相同。
疑问
- 为何会出现这种情况?
- 如何实现点击按钮关闭弹窗后,再次点击按钮能正常弹出下一个提示弹窗?
相关代码
JavaScript代码
document.getElementById("submit").addEventListener("click", calc); function calc() { let a = parseFloat(document.getElementById("a").value); let b = parseFloat(document.getElementById("b").value); let c = parseFloat(document.getElementById("c").value); let output = document.getElementById("output"); if (a === 0) { $(this).popover({ placement: "bottom", content: '<textarea class="popover-textarea"></textarea>', template: '<div class="popover"><div class="arrow"></div>' + '<div class="row"><div class="col-3 my-auto">' + '</div><div class="popover-content col-9">You have chosen 0, this needs to be non-zero' + "</div></div>", }); $(this).popover("show"); $(this).click(function() { $(this).popover("hide"); }); return false; } else if (b === c) { $(this).popover({ placement: "bottom", content: '<textarea class="popover-textarea"></textarea>', template: '<div class="popover"><div class="arrow"></div>' + '<div class="row"><div class="col-3 my-auto">' + '</div><div class="popover-content col-9">You have chosen b and c to be the same, they need to be different' + "</div></div>", }); $(this).popover("show"); $(this).click(function() { $(this).popover("hide"); }); return false; } }
HTML代码
<form> <input type="number" id="a"> <input type="number" id="b"> <input type="number" id="c"> <button type="button" id="submit">Hit me</button> </form> <p id="output"></p> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" /> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
问题解答
1. 问题原因
- 重复绑定点击事件:每次执行
calc函数时,都会给按钮新增一个click事件用于隐藏弹窗。第一次点击触发a===0逻辑后,按钮上绑定了隐藏事件;第二次点击时,这个隐藏事件会先执行,随后才会触发calc,但此时弹窗已被隐藏,且Bootstrap不会重复初始化已存在的Popover实例,导致第二个条件的弹窗无法显示。 - Popover实例未更新:Bootstrap的Popover组件初始化后,直接调用
popover()修改配置不会生效,因为组件实例已存在,必须先销毁旧实例才能重新配置。
2. 解决方案
优化后的代码
document.getElementById("submit").addEventListener("click", calc); const $submitBtn = $("#submit"); // 定义弹窗模板,用占位符替换提示内容 const baseTemplate = '<div class="popover"><div class="arrow"></div>' + '<div class="row"><div class="col-3 my-auto"></div>' + '<div class="popover-content col-9">{{msg}}</div></div>'; // 初始化Popover,设置手动触发 $submitBtn.popover({ placement: "bottom", content: '<textarea class="popover-textarea"></textarea>', template: baseTemplate.replace('{{msg}}', ''), trigger: 'manual' }); // 仅绑定一次弹窗隐藏事件 $submitBtn.on('click', function(e) { const popoverInstance = $submitBtn.data('bs.popover'); if (popoverInstance && popoverInstance._isShown) { $submitBtn.popover('hide'); e.stopImmediatePropagation(); // 阻止触发calc函数 } }); function calc() { const a = parseFloat(document.getElementById("a").value); const b = parseFloat(document.getElementById("b").value); const c = parseFloat(document.getElementById("c").value); if (a === 0) { // 销毁旧实例,重新配置弹窗内容 $submitBtn.popover('dispose'); $submitBtn.popover({ placement: "bottom", content: '<textarea class="popover-textarea"></textarea>', template: baseTemplate.replace('{{msg}}', '你选择了0,该值不能为0'), trigger: 'manual' }); $submitBtn.popover("show"); return; } else if (b === c) { $submitBtn.popover('dispose'); $submitBtn.popover({ placement: "bottom", content: '<textarea class="popover-textarea"></textarea>', template: baseTemplate.replace('{{msg}}', '你选择的b和c相同,它们必须不同'), trigger: 'manual' }); $submitBtn.popover("show"); return; } }
核心优化点
- 仅绑定一次弹窗隐藏事件,避免重复绑定导致的事件冲突
- 使用
trigger: 'manual'手动控制弹窗显示/隐藏,规避Bootstrap默认触发逻辑的干扰 - 切换弹窗内容时,先销毁旧的Popover实例,再重新初始化新配置的实例,确保内容更新生效
- 点击事件中判断弹窗状态:若弹窗正在显示则隐藏并阻止执行校验逻辑,否则正常执行校验
内容的提问来源于stack exchange,提问作者Paul Davis
相关产品推荐
相关产品推荐

