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

XMLHttpRequest请求后返回HTML内script脚本不生效的解决方法

问题根因

你现有代码跑不通的直接原因是setInnerHTML方法里的API调用错误:DOM元素根本没有setAttributes这个复数命名的方法,正确的属性设置方法是单数形式的setAttribute,所以你动态创建的script标签属性复制逻辑完全没生效,脚本自然不会执行。
就算你把这个API名改对,这种靠AJAX拉取整段带script的HTML、再手动替换script标签强制执行的思路也非常不推荐:本质是在页面里动态执行远程返回的任意代码,存在极大的XSS安全隐患,同时还会出现执行时序不可控、DOM节点找不到、调试困难等一堆问题。

最优无刷新实现方案

彻底抛弃“拉取带渲染逻辑的HTML片段再强制执行脚本”的思路,做最基础的前后端职责拆分:

  • 后端接口只返回纯JSON格式的搜索结果数据,不要返回混杂script标签的HTML内容
  • 所有渲染逻辑全部放在主页面(index.html)中,拿到接口返回的JSON数据后直接在当前页面完成DOM拼接、渲染到demo容器
  • 全程不需要动态插入、执行远程脚本,没有安全风险,逻辑可控调试方便

具体落地代码

1. 后端接口调整

把原来ajax_info.html里硬编码的searchResults数据抽出来,做成专门的搜索接口(比如路径设为/api/search),接口接收POST请求,直接返回纯JSON格式的搜索结果,结构参考:

{
  "response": {
    "docs": [
      {
        "es_title": "搜索结果标题",
        "es_description": "搜索结果摘要描述",
        "author": "作者名",
        "site": "来源站点",
        "es_date": "2024-05-20"
      }
    ]
  }
}

2. 主页面逻辑调整

把原来写在ajax_info.html里的渲染逻辑移到index.html中,改造后的loadDoc方法如下:

function loadDoc() {
  const resultContainer = document.getElementById("demo");
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState !== XMLHttpRequest.DONE) return;
    if (this.status !== 200) {
      resultContainer.innerHTML = "<div class='text-danger p-3'>搜索结果加载失败,请重试</div>";
      return;
    }
    try {
      // 解析接口返回的JSON数据
      const searchResults = JSON.parse(this.responseText);
      const docList = searchResults.response.docs;
      let resultHtml = "";
      // 拼接结果DOM
      for (let i = 0; i < docList.length; i++) {
        const item = docList[i];
        resultHtml += `
          <div class='p-3 border rounded-3'>
            <a href=''>
              <strong class='text-primary largeText'>${item.es_title}</strong>
            </a>
            <div class='largeText'>${item.es_description}</div>
            <div>${item.author}</div>
            <div>${item.site}</div>
            <div>${item.es_date}<a class='text-success'> ${item.site}</a></div>
          </div>
        `;
      }
      // 一次性把渲染好的内容插入容器
      resultContainer.innerHTML = resultHtml;
    } catch (err) {
      console.error("结果解析出错:", err);
      resultContainer.innerHTML = "<div class='text-danger p-3'>搜索结果格式异常,请稍后重试</div>";
    }
  };
  xhttp.open("POST", "/api/search", true);
  // 传搜索参数的时候设置对应请求头
  xhttp.setRequestHeader("Content-Type", "application/json");
  xhttp.send(JSON.stringify({
    keyword: document.getElementById("searchInput").value.trim()
  }));
}
临时兼容方案(不推荐生产使用)

如果你暂时不想调整架构,非要沿用现有拉取ajax_info.html的逻辑,先把两个问题修复:

  1. 把代码里的newScript.setAttributes改成newScript.setAttribute,修正API调用错误
  2. 确保ajax_info.html里id为demo2的div节点和script标签一起被返回,不然脚本执行时找不到对应DOM节点会直接中断

风险提示:这种方案会直接执行接口返回的任意脚本代码,一旦接口内容被篡改,就会被注入恶意代码执行,存在严重安全隐患。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 20:54:18