解决jQuery交替点击按钮时事件重复触发、代码多次执行问题
问题根因
每次点击「回复按钮1」触发的Ajax请求成功后,都会执行post_reply()函数,该函数会给#reply-btn-2新增一个独立的点击事件监听器。jQuery不会自动清除同元素上已绑定的同类型事件监听器,你点击N次回复按钮1,回复按钮2上就会绑定N个点击事件,后续点击回复按钮2时,所有绑定过的监听器会依次执行,就会出现逻辑多次触发的问题。
修复方案(完全匹配需求)
需求明确要求:post_reply对应逻辑仅在第一次回复按钮1的Ajax调用成功、且点击回复按钮2时才执行,修复逻辑如下:
- 增加布尔状态标记,记录回复按钮1的首次Ajax请求是否已成功完成,避免重复激活回复按钮2的逻辑
- 全局仅绑定一次回复按钮2的点击事件,通过状态标记控制逻辑是否执行,从根源避免重复绑定问题
完整修复代码:
// 首次请求状态标记,默认未完成 let firstReplyRequestSuccess = false; // 全局仅绑定一次回复按钮2的点击事件 $('#reply-btn-2').on('click', function(){ // 首次请求未完成时直接拦截,不执行后续逻辑 if (!firstReplyRequestSuccess) return; const text2 = 'Reply 2<br>'; $.ajax({ url: 'ajax.php', type: 'POST', data: {'submit':1, 'post':2} }).done(function(response){ $('.place-replies-here').append(text2); }); }); $('#reply-btn-1').on('click', function(){ const text1 = 'Reply 1<br>'; $.ajax({ url: 'ajax.php', type: 'POST', data: {'submit':1, 'post':2} }).done(function(response){ $('.place-replies-here').append(text1); // 首次成功后更新标记,后续重复点击按钮1不会改变状态 if (!firstReplyRequestSuccess) { firstReplyRequestSuccess = true; } }); });
对应HTML代码和原逻辑一致:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <div class="place-replies-here"></div> <div id="reply-btn-1" style="height:40px; width:100px;background:green;color:#fff; padding:5px; margin:8px;" class="reply-btn"> Reply 1 </div> <div id="reply-btn-2" style="height:40px; width:100px;background:green;color:#fff;padding:5px; margin:8px;" class="btn btn-success reply-btn"> Reply 2 </div>
动态按钮场景适配
如果你的实际业务中,回复按钮2是第一次Ajax成功后才动态插入页面的(不是页面初始加载就存在),可以用事件委托实现单次绑定,不需要把事件绑定逻辑写在Ajax回调里:
let firstReplyRequestSuccess = false; // 给页面初始就存在的静态父元素绑定委托事件,动态生成的按钮2也能响应 $(document).on('click', '#reply-btn-2', function(){ if (!firstReplyRequestSuccess) return; // 业务逻辑和上述代码一致 const text2 = 'Reply 2<br>'; $.ajax({ url: 'ajax.php', type: 'POST', data: {'submit':1, 'post':2} }).done(function(response){ $('.place-replies-here').append(text2); }); }); // 按钮1的点击逻辑不变
避坑提示:如果一定要把事件绑定写在Ajax回调的
post_reply函数里,绑定事件前必须先解绑元素上已有的同类型事件,写法为$('#reply-btn-2').off('click').on('click', function(){ /* 逻辑 */ }),否则必然出现重复触发问题。
内容的提问来源于stack exchange,提问作者programmer777
相关产品推荐
相关产品推荐

