模态框多次关闭后点击Mint按钮,函数重复触发问题排查
模态框按钮点击事件重复触发问题
问题现象
每次打开并关闭模态框后,再次点击模态框内的「Mint」按钮(#final-mint-btn),mintErc20Token函数中的console.log("Test");会重复触发,触发次数等于此前打开模态框的总次数(例如打开关闭4次后,第4次点击按钮会触发4次日志输出)。
相关代码
模态框HTML代码
<div class="modal fade" id="token-minting-modal" data-backdrop="false" role="dialog" > <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="minting-modal-label">How many to mint?</h5> </div> <form> <div class="modal-body"> <div id="minting-modal-msg" class="text-danger"></div> <div class="form-group"></div> <div class="form-group"> <label for="token-amount"> Amount: </label> <input type="text" name="token_amount" id="token-amount" placeholder="1000" /> </div> <div class="form-group"> <div id="minting-results"> </div> </div> </div> <div class="modal-footer"> <button type="button" id="minting-modal-close-btn" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="button" id="final-mint-btn" class="btn btn-primary">Mint</button> </div> </form> </div> </div> </div>
触发模态框的按钮代码
<button type="button" class="btn btn-default btn-sm" id="mint-token-btn" onclick="mintErc20Token('0x3b757', '0x867c099011', '968');">Mint Tokens</button>
核心函数代码
async function mintErc20Token( senderWallet, contractAddress, postId ) { let tokenAmount = ''; //Display the modal pop-up jQuery("#token-minting-modal").modal("show"); jQuery("#token-minting-modal").appendTo("body"); //jQuery("#mint-token-btn").attr("disabled"); jQuery("#minting-results").hide(); jQuery('#token-minting-modal').on('hidden.bs.modal', function () { jQuery('form').trigger('reset'); // to reset the form }) jQuery('#final-mint-btn').click( async function() { ... //DEBUG console.log("Test"); }); }
问题原因
每次调用mintErc20Token函数时,都会给#final-mint-btn绑定一次新的click事件,且未移除之前绑定的事件,导致事件处理函数被叠加绑定。同时,hidden.bs.modal事件也会被重复绑定,虽影响较小但属于冗余操作。
解决方案
方案1:绑定前先解绑事件
在给按钮绑定新的click事件前,先移除已存在的同类型事件,避免叠加:
async function mintErc20Token( senderWallet, contractAddress, postId ) { let tokenAmount = ''; //Display the modal pop-up jQuery("#token-minting-modal").modal("show"); jQuery("#token-minting-modal").appendTo("body"); jQuery("#minting-results").hide(); // 解绑之前的click事件,再绑定新事件 jQuery('#final-mint-btn').off('click').on('click', async function() { // ... 原有业务逻辑 console.log("Test"); }); } // 将模态框隐藏事件移到函数外部,仅绑定一次 jQuery('#token-minting-modal').on('hidden.bs.modal', function () { jQuery('form').trigger('reset'); })
方案2:将事件绑定移到函数外部(推荐)
把按钮点击事件和模态框隐藏事件的绑定逻辑移出mintErc20Token函数,确保只绑定一次:
// 页面加载完成后,一次性绑定所有事件 jQuery(function() { // 模态框隐藏事件 jQuery('#token-minting-modal').on('hidden.bs.modal', function () { jQuery('form').trigger('reset'); }); // Mint按钮点击事件 jQuery('#final-mint-btn').on('click', async function() { // 通过元素data属性获取参数 const { senderWallet, contractAddress, postId } = jQuery(this).data(); // ... 原有业务逻辑 console.log("Test"); }); }); async function mintErc20Token( senderWallet, contractAddress, postId ) { let tokenAmount = ''; // 将参数存入按钮的data属性,供点击事件使用 jQuery('#final-mint-btn').data({ senderWallet, contractAddress, postId }); //Display the modal pop-up jQuery("#token-minting-modal").modal("show"); jQuery("#token-minting-modal").appendTo("body"); jQuery("#minting-results").hide(); }
这种方式从根源避免了重复绑定问题,代码结构更清晰。
内容的提问来源于stack exchange,提问作者ratib90486
相关产品推荐
相关产品推荐

