You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击分页按钮触发大量Ajax请求问题及解决方案咨询

解决Ajax加载页面后重复触发大量请求的问题

咱们先把问题根源揪出来——你遇到的大量重复请求,本质是脚本重复执行导致事件监听器被多次绑定,而page_1.php没问题是因为它的代码执行逻辑和其他页面不一样。

为什么page_1正常,page_2/page_3出问题?

  • page_1的脚本是包裹在DOMContentLoaded事件里的:这个事件在页面初始化时只会触发一次,所以executeAjax1的点击事件只绑定了一次,后续即使加载其他页面的脚本,也不会重新执行这段绑定逻辑。
  • page_2/page_3的脚本是直接执行的:每次你通过eval执行页面中所有<script>内容时,这段代码会重新跑一遍——也就是又给executeAjax2/executeAjax3绑定了一次点击事件。点一次按钮,所有绑定的监听器都会触发,发送一次请求;而每个请求完成后又会eval所有脚本,再绑定更多监听器,恶性循环下去,请求次数自然指数级增长,直接把浏览器搞卡。

解决方案:避免重复执行脚本+事件只绑定一次

核心思路是:只执行新加载的Ajax内容里的脚本,不要重复执行页面中已有的脚本,同时确保事件监听器不会被多次绑定。

1. 改进脚本执行逻辑(替换你当前的eval代码)

不要获取页面中所有<script>的内容来eval,而是只提取刚通过Ajax加载到容器里的新脚本,创建新的<script>标签来执行它们,执行完后从容器里移除这些脚本标签,避免下次重复获取。

比如修改page_1.php里的Ajax回调:

xhr1.onreadystatechange = function(){
  if(xhr1.readyState === 4){
    var ajaxContainer = document.getElementById('ajax1');
    ajaxContainer.innerHTML = xhr1.responseText;
    
    // 只执行新加载的脚本
    var newScripts = ajaxContainer.getElementsByTagName('script');
    var scriptsToExecute = [];
    // 先收集所有新脚本内容,避免移除时影响遍历
    for (var i = 0; i < newScripts.length; i++) {
      scriptsToExecute.push(newScripts[i].innerHTML);
      ajaxContainer.removeChild(newScripts[i]);
    }
    // 创建新script标签执行
    scriptsToExecute.forEach(function(scriptContent) {
      var script = document.createElement('script');
      script.textContent = scriptContent;
      document.body.appendChild(script);
      // 可选:执行后移除临时script标签
      script.remove();
    });
  }
}

2. 确保事件只绑定一次

把page_2.php和page_3.php的脚本也改成包裹在DOMContentLoaded里(和page_1一样),这样即使脚本被执行多次,DOMContentLoaded也只会触发一次,避免重复绑定事件:

修改page_2.php的脚本:

<script>
document.addEventListener('DOMContentLoaded', function(){
  var execute_sendAjax2 = document.getElementById('executeAjax2');
  execute_sendAjax2.addEventListener('click', sendAjax2);
  
  function sendAjax2(){
    var xhr2= new XMLHttpRequest();
    xhr2.onreadystatechange = function(){
      if(xhr2.readyState === 4){
        var ajaxContainer = document.getElementById('ajax2');
        ajaxContainer.innerHTML= xhr2.responseText;
        
        // 同样使用新的脚本执行逻辑
        var newScripts = ajaxContainer.getElementsByTagName('script');
        var scriptsToExecute = [];
        for (var i = 0; i < newScripts.length; i++) {
          scriptsToExecute.push(newScripts[i].innerHTML);
          ajaxContainer.removeChild(newScripts[i]);
        }
        scriptsToExecute.forEach(function(scriptContent) {
          var script = document.createElement('script');
          script.textContent = scriptContent;
          document.body.appendChild(script);
          script.remove();
        });
      }
    }
    xhr2.open('POST','page_3.php');
    xhr2.send();
  }
});
</script>

page_3.php做同样的修改即可。

额外优化:使用事件委托(可选)

如果页面结构允许,也可以用事件委托来避免直接绑定按钮的事件,这样不管按钮什么时候加载,都只会有一个监听器:

比如在page_1的初始化代码里添加:

document.addEventListener('click', function(e) {
  if(e.target.id === 'executeAjax1') {
    sendAjax1();
  } else if(e.target.id === 'executeAjax2') {
    sendAjax2();
  } else if(e.target.id === 'executeAjax3') {
    sendAjax3();
  }
});

这样就不需要在每个页面里单独绑定按钮事件了,从根源上避免重复绑定的问题。

验证效果

修改后,点击page_2/page_3的按钮时,每次点击只会触发一次Ajax请求,而且脚本只会执行新加载的内容,不会重复绑定事件,浏览器也不会再冻结了。

内容的提问来源于stack exchange,提问作者user9767744

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:36:32