提交预约评分表单时jQuery事件为何更新表格内所有已完成预约行?
问题原因
- 事件委托重复绑定:你将
submit事件的绑定逻辑写在了for循环内部,每渲染一条「已完成」的预约记录,就会给.tabela-clientes新增一个submit事件监听器。假设你有N条已完成预约,提交任意一个表单时都会触发N次事件回调,依次把所有预约ID都发送了更新请求。 - 循环变量闭包陷阱:事件回调触发时循环已经执行完毕,所有回调拿到的
marcacao[i]._id大概率都是最后一条已完成预约的ID,也会导致更新逻辑异常。 - 多余的点击逻辑冲突:提交按钮上同时写了两个
onclick事件,其中window.location.reload()会在点击后立即刷新页面,可能导致部分AJAX请求还没完成就被中断,也会引发异常行为。
修复方案
- 第一步:将
submit事件委托的绑定逻辑移出for循环,全局只绑定一次即可,事件委托本身就支持动态生成的元素触发。 - 第二步:在渲染表单时,把当前预约的
_id存入表单的自定义data-*属性中,提交时直接从当前触发事件的表单上取ID,不再依赖循环变量。 - 第三步:删除按钮上冗余的
onclick事件,页面刷新逻辑放到AJAX请求的success回调中,保证更新成功后再刷新页面。
修复后核心代码示例
function buildTable(marcacao) { let table = document.getElementById('tabelaCliente') // 事件绑定移到循环外,全局只绑一次 $('.tabela-clientes').off('submit', '.avaliacao').on('submit', '.avaliacao', function(e) { e.preventDefault(); let formData2 = $(this).serialize(); let formAction2 = $(this).attr('action'); // 从当前表单的自定义属性取预约ID let marcacaoId = $(this).data('id'); $.ajax({ method: 'PUT', url: formAction2 + '/' + marcacaoId, dataType: 'json', data: formData2, success: function(data) { console.log(data); // 请求成功后再刷新页面 window.location.reload(); } }) }) for (let i = 0; i < marcacao.length; i++) { if (marcacao[i].state == "Pendente") { let row = `<tr> <td>${marcacao[i].address}</td> <td>${marcacao[i].date}</td> <td>${marcacao[i].hour}</td> <td>${marcacao[i].type}</td> <td>${marcacao[i].state}</td> </tr>` table.innerHTML += row } else { // 给form加data-id属性存储当前预约ID,删除按钮冗余onclick、重复的select id let row = `<tr> <td>${marcacao[i].address}</td> <td>${marcacao[i].date}</td> <td>${marcacao[i].hour}</td> <td>${marcacao[i].type}</td> <td>${marcacao[i].state}</td> <td> <div class="form-group col-xs-12 pl-lg-3"> <form action="/auth/avaliacaoPUT" method="POST" class="avaliacao" data-id="${marcacao[i]._id}"> <div class="form-group"> <select name="aval_client" class="form-control-select"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> <button type="submit" class="btn btn-fill btn-primary">Submeter</button> </div> </form> </div> </td> </tr>` table.innerHTML += row } } }
内容的提问来源于stack exchange,提问作者Lolstroop
相关产品推荐
相关产品推荐

