繁体   English   中英

引导模式关闭事件为什么会“堆栈”?

[英]Why does bootstrap modal close event “stack”?

我正在尝试制作一个可以多次添加到页面的确认控件,但是我偶然发现了导致这些控件彼此“接触”的错误(显然,我想让它们独立工作)。

我为此使用了Bootstrap,并且使用了尽可能少的jQuery(由于调试)。

经过切片后,我发现在代码中,Bootstrap关闭功能将多次运行,从而导致此问题。 会有人碰巧知道为什么该Bootstrap函数会多次运行吗?

这将是我的问题的原因

$("").on("hidden.bs.modal", function (e) {
  //Why does this stack?
  alert("Why does this stack?");
});

这是我的代码的上下文 ,它将在其中多次运行:

 //Yes selector const positiveSelector = ".positive"; //No selector const negativeSelector = ".negative"; //Confirm? selector const confirmSelector = ".init-confirm" //Pending selector const pendingSelector = ".pending"; //Yes ele const positiveNodes = document.querySelectorAll(positiveSelector); //No ele const negativeNodes = document.querySelectorAll(negativeSelector); //Confirm? ele const confirmNodes = document.querySelectorAll(confirmSelector); //Pending ele const pendingNodes = document.querySelectorAll(pendingSelector); //Modal related: const $modalInit = $(".modal").html(); const targetModal = $("#bs-modal-xl"); positiveNodes.forEach(node => node.addEventListener("click", function () { let thisNode = this; thisNode.classList.add("btn-success"); thisNode.parentNode.querySelectorAll(negativeSelector).forEach(node => node.classList.remove("btn-warning")); thisNode.parentNode.parentNode.querySelectorAll(confirmSelector).forEach(node => node.removeAttribute("disabled")); })); negativeNodes.forEach(node => node.addEventListener("click", function () { let thisNode = this; thisNode.classList.add("btn-warning"); thisNode.parentNode.querySelectorAll(positiveSelector).forEach(node => node.classList.remove("btn-success")); thisNode.parentNode.parentNode.querySelectorAll(confirmSelector).forEach(node => node.setAttribute("disabled", "")); thisNode.parentNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.style.display = "none"); })); confirmNodes.forEach(node => node.addEventListener("click", function () { let thisNode = this; thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.style.display = "inline-block"); thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.classList.remove("btn-warning")); thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.classList.add("btn-danger")); thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.textContent = "Pending"); //Populate modal: ModalHandler($(".my-ele").clone(), "My ele", undefined, true, true); $(".modal .my-ele").show(); //Show Modal: targetModal.modal(); $(".modal").on("click", ".my-ele button", function () { targetModal.modal("hide"); }); //When closing Modal: targetModal.on("hidden.bs.modal", function (e) { //Why does this stack? alert("Why does this stack?"); }); })); //Modal handling (not required when not using Modal): function ModalHandler(content, title, footer = "", bigCloseBtn = false, emptyFooter = false) { $(".modal h4.modal-title").text(title); $(".modal .modal-body").html(content); if (footer != "" && footer != undefined) { $(".modal .modal-footer").html(footer); } if (bigCloseBtn) { $(".modal .modal-content .modal-header button.close").css("float", "right"); $(".modal .modal-content .modal-header button.close").addClass("btn btn-lg btn-danger"); //$(".modal .modal-content .modal-header button.close").html("close"); $(".modal .modal-content .modal-header button.close").removeClass("close"); } if (emptyFooter) { $(".modal .modal-content .modal-footer").html(""); } } $(".modal").on("hidden.bs.modal", function () { $(".modal").html($modalInit); }); 
 #foo-container { padding: 5px; } .pending { display: none; } .my-ele { display: none; } 
 <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <div class="modal" id="bs-modal-xl" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <p>One fine body&hellip;</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div> </div> </div> <div id="foo-container"> <div class="confirmation-box"> <div class="btn-group btn-group-lg" role="group" aria-label="..."> <button type="button" class="btn btn-success positive">Yes</button> <button type="button" class="btn btn-warning negative">No</button> </div> <button type="button" class="btn btn-lg btn-danger init-confirm" disabled>Confirm?</button> <button type="button" class="btn btn-lg btn-danger pending" disabled>Pending</button> </div> <br /> <div class="confirmation-box"> <div class="btn-group btn-group-lg" role="group" aria-label="..."> <button type="button" class="btn btn-success positive">Yes</button> <button type="button" class="btn btn-warning negative">No</button> </div> <button type="button" class="btn btn-lg btn-danger init-confirm" disabled>Confirm?</button> <button type="button" class="btn btn-lg btn-danger pending" disabled>Pending</button> </div> </div> <div class="my-ele"> <button type="button" class="btn btn-lg btn-success">Clicky</button> </div> 

的jsfiddle

为了重现我的问题,必须通过单击“是”按钮以启用“确认?”来打开模态。 按钮,然后单击此按钮。 然后退出模态。 该事件将运行一次,但是,当重复打开和关闭模式时,警报将开始堆叠(由于事件由于某种原因而开始堆叠,我不理解)。

我之所以有

.on("hidden.bs.modal", function (e) {}); eventListener

任何

<button type="button" class="btn btn-lg btn-danger init-confirm" disabled>Confirm?</button>

因为我需要将clicked元素作为参数传递给外部函数。

我可以使模式关闭函数只运行一次而不是“让它们堆积”吗?

这是因为该事件一遍targetModal.on应用于targetModal.on 你需要把它off

targetModal.off();

 //Yes selector const positiveSelector = ".positive"; //No selector const negativeSelector = ".negative"; //Confirm? selector const confirmSelector = ".init-confirm" //Pending selector const pendingSelector = ".pending"; //Yes ele const positiveNodes = document.querySelectorAll(positiveSelector); //No ele const negativeNodes = document.querySelectorAll(negativeSelector); //Confirm? ele const confirmNodes = document.querySelectorAll(confirmSelector); //Pending ele const pendingNodes = document.querySelectorAll(pendingSelector); //Modal related: const $modalInit = $(".modal").html(); const targetModal = $("#bs-modal-xl"); positiveNodes.forEach(node => node.addEventListener("click", function() { let thisNode = this; thisNode.classList.add("btn-success"); thisNode.parentNode.querySelectorAll(negativeSelector).forEach(node => node.classList.remove("btn-warning")); thisNode.parentNode.parentNode.querySelectorAll(confirmSelector).forEach(node => node.removeAttribute("disabled")); })); negativeNodes.forEach(node => node.addEventListener("click", function() { let thisNode = this; thisNode.classList.add("btn-warning"); thisNode.parentNode.querySelectorAll(positiveSelector).forEach(node => node.classList.remove("btn-success")); thisNode.parentNode.parentNode.querySelectorAll(confirmSelector).forEach(node => node.setAttribute("disabled", "")); thisNode.parentNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.style.display = "none"); })); confirmNodes.forEach(node => node.addEventListener("click", function() { let thisNode = this; thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.style.display = "inline-block"); thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.classList.remove("btn-warning")); thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.classList.add("btn-danger")); thisNode.parentNode.querySelectorAll(pendingSelector).forEach(node => node.textContent = "Pending"); //Populate modal: ModalHandler($(".my-ele").clone(), "My ele", undefined, true, true); $(".modal .my-ele").show(); //Show Modal: targetModal.modal(); $(".modal").on("click", ".my-ele button", function() { targetModal.modal("hide"); }); //When closing Modal: targetModal.on("hidden.bs.modal", function(e) { //Why does this stack? alert("Why does this stack?"); targetModal.off(); }); })); //Modal handling (not required when not using Modal): function ModalHandler(content, title, footer = "", bigCloseBtn = false, emptyFooter = false) { $(".modal h4.modal-title").text(title); $(".modal .modal-body").html(content); if (footer != "" && footer != undefined) { $(".modal .modal-footer").html(footer); } if (bigCloseBtn) { $(".modal .modal-content .modal-header button.close").css("float", "right"); $(".modal .modal-content .modal-header button.close").addClass("btn btn-lg btn-danger"); //$(".modal .modal-content .modal-header button.close").html("close"); $(".modal .modal-content .modal-header button.close").removeClass("close"); } if (emptyFooter) { $(".modal .modal-content .modal-footer").html(""); } } $(".modal").on("hidden.bs.modal", function() { $(".modal").html($modalInit); }); 
 #foo-container { padding: 5px; } .pending { display: none; } .my-ele { display: none; } 
 <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <div class="modal" id="bs-modal-xl" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <p>One fine body&hellip;</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div> </div> </div> <div id="foo-container"> <div class="confirmation-box"> <div class="btn-group btn-group-lg" role="group" aria-label="..."> <button type="button" class="btn btn-success positive">Yes</button> <button type="button" class="btn btn-warning negative">No</button> </div> <button type="button" class="btn btn-lg btn-danger init-confirm" disabled>Confirm?</button> <button type="button" class="btn btn-lg btn-danger pending" disabled>Pending</button> </div> <br /> <div class="confirmation-box"> <div class="btn-group btn-group-lg" role="group" aria-label="..."> <button type="button" class="btn btn-success positive">Yes</button> <button type="button" class="btn btn-warning negative">No</button> </div> <button type="button" class="btn btn-lg btn-danger init-confirm" disabled>Confirm?</button> <button type="button" class="btn btn-lg btn-danger pending" disabled>Pending</button> </div> </div> <div class="my-ele"> <button type="button" class="btn btn-lg btn-success">Clicky</button> </div> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM