如何在JavaScript中重置XHR以避免Ajax重复提交?
解决Bootstrap模态框Ajax提交多次触发的问题
问题根源
你每次点击「创建商品分类」按钮时,都会执行document.getElementById('save_btn').addEventListener('click', ...),这会给同一个提交按钮重复绑定点击事件。第一次点击创建按钮绑定1次事件,第二次绑定2次,以此类推,导致每次提交时触发对应次数的Ajax请求,出现提交操作逐次递增的情况。这个问题和Ajax请求本身无关,核心是事件重复绑定。
解决方案
下面提供两种可行的修复方式:
方式1:使用事件委托(推荐)
将提交按钮的点击事件监听绑定到模态框的父容器上(比如modal-body),只需要绑定一次,无论模态框内容如何动态加载,事件都会生效,从根源避免重复绑定。
修改后的代码:
// 提前绑定事件委托,仅执行一次 document.getElementById('modal-body').addEventListener('click', function(e) { // 判断点击的元素是否是提交按钮 if (e.target.id === 'save_btn') { e.preventDefault(); console.log('save_btn') var xhr = new XMLHttpRequest(); xhr.open('POST', `../includes/functions.php`, true) xhr.onload = function() { if (xhr.status == 200) { console.log(xhr.response) if (xhr.response == 'category name add successfully! ') { document.getElementById('close_modal_btn').click(); showMessage(xhr.response, 'Add') console.log(xhr.responseText) } else { showMessage(xhr.response, 'Remove') document.getElementById('logo_box').innerHTML = `<span class='text-danger'>${xhr.response}</span>`; } setTimeout(() => { document.getElementById('table-body').innerHTML = ''; defaultLoad(); console.log("data Loaded") }, 5000) } } const formData = new FormData(document.getElementById('add_category_form')) xhr.send(formData); } }); // 点击创建商品分类按钮加载模态框内容 document.getElementById('add_category').addEventListener('click', () => { var xhr = new XMLHttpRequest(); xhr.open("GET", 'add.php', true); console.log("add_category") xhr.onload = function() { if (this.status == 200) { document.getElementById('exampleModalLabel').innerHTML = 'Create Product Category'; document.getElementById('modal-body').innerHTML = this.response; dynamicChangePicture(); onChangeCategoryName('category_name'); } } xhr.send(); })
方式2:每次加载内容时清除旧事件
将提交逻辑抽成独立函数,每次动态加载模态框内容后,通过克隆提交按钮的方式清除旧的事件监听,再绑定新的事件。
修改后的代码:
// 抽离提交逻辑为独立函数 function handleSaveCategory(e) { e.preventDefault(); console.log('save_btn') var xhr = new XMLHttpRequest(); xhr.open('POST', `../includes/functions.php`, true) xhr.onload = function() { if (xhr.status == 200) { console.log(xhr.response) if (xhr.response == 'category name add successfully! ') { document.getElementById('close_modal_btn').click(); showMessage(xhr.response, 'Add') console.log(xhr.responseText) } else { showMessage(xhr.response, 'Remove') document.getElementById('logo_box').innerHTML = `<span class='text-danger'>${xhr.response}</span>`; } setTimeout(() => { document.getElementById('table-body').innerHTML = ''; defaultLoad(); console.log("data Loaded") }, 5000) } } const formData = new FormData(document.getElementById('add_category_form')) xhr.send(formData); } // 点击创建商品分类按钮加载模态框内容 document.getElementById('add_category').addEventListener('click', () => { var xhr = new XMLHttpRequest(); xhr.open("GET", 'add.php', true); console.log("add_category") xhr.onload = function() { if (this.status == 200) { document.getElementById('exampleModalLabel').innerHTML = 'Create Product Category'; document.getElementById('modal-body').innerHTML = this.response; dynamicChangePicture(); onChangeCategoryName('category_name'); // 克隆按钮清除旧事件,再绑定新事件 const saveBtn = document.getElementById('save_btn'); const newSaveBtn = saveBtn.cloneNode(true); saveBtn.parentNode.replaceChild(newSaveBtn, saveBtn); newSaveBtn.addEventListener('click', handleSaveCategory); } } xhr.send(); })
说明
两种方式都能解决重复提交的问题,事件委托更高效,不需要每次处理元素的克隆或事件移除,推荐使用。
内容的提问来源于stack exchange,提问作者Sultan afghan
相关产品推荐
相关产品推荐

