【问题标题】:Execute script sourced to an external file loaded from AJAX执行源自从 AJAX 加载的外部文件的脚本
【发布时间】:2019-03-22 12:15:10
【问题描述】:

这是一个与 AJAX 相关的非常常见的问题,但我似乎找不到适合我的情况的问题,因为他们中的大多数使用 jQuery,以及其他原因。可能我的效率不高/不推荐,但不管怎样,我们开始吧。

我有一个按钮 [假设我们有一个引用它,因为它被称为 btn]。

它监听点击事件。当用户单击该按钮时,它会向主 HTML/CSS/JS 文件所在目录中的 .txt 文件发出 AJAX 请求。我们就叫它test.txt吧。

现在,它改变了<html> 的innerHTML(不是head/body,是html),innerHTML 是来自AJAX 请求的响应。

test.txt 保存 HTML 代码。在那个 HTML 代码中有<script src="another-js-file.js">。 这没有被执行,这就是问题所在。

在你对我尖叫之前INNERHTML 不会执行任何脚本我知道。我已经看到其他答案说要在另一个 div 中的 div 中创建 <script> 标签,但它似乎不适用于外部 js 文件,并且解决方案确实使用了 innerHTML。

好的,这是一个草图:

 btn.onclick = function(){
   var xhr = new XMLHttpRequest();
   xhr.onreadystatechange = function(){
    if(xhr.readyState = XMLHttpRequest.DONE){
        document.documentElement.innerHTML = this.responseText;
     }
   }
   xhr.open("GET", "./test.txt");
   xhr.send();
   }

test.txt 所在的位置:

<head>
   <title>Document</title>
   <link rel="stylesheet" href="test.css">
   <script src="another-js-file.js"></script>
</head>

<body>
  <h1>Hello World!</h1>
</body>

没有 jQuery。

【问题讨论】:

  • 没有 jQuery。 ????
  • 是的,只为 AJAX 使用 40KB 库是多余的。我完全赞成香草。

标签: javascript html ajax xmlhttprequest


【解决方案1】:

我注意到您在最初的 XHR 请求中写道:

if(xhr.readyState = XMLHttpRequest.DONE)

这实际上应该是三重 === 而不是单一的。

将此函数添加到您发出 XHR 请求的初始 JS 文件中,

function setInnerHtml(el, html) {
  el.innerHTML = html;
  // Get all the scripts from the new HTML
  const scripts = el.querySelectorAll('script');

  // Loop through all the scripts
  for (let i = 0; i < scripts.length; i++)
  {
    // Create a new script
    const s = document.createElement('script');

    // Go through all the attributes on the script
    for (let j = 0; j < scripts[i].attributes.length; j++) {
      const a = scripts[i].attributes[j];
      // Add each attribute to the new script
      s.setAttribute(a.name, a.value);
    }

    // Incase there is code inside the script tag
    // Example: <script>alert</script>
    s.innerHTML = scripts[i].innerHTML;

    // Append the new script to the head (you could change this to the end of the body as well)
    document.head.appendChild(s);
  }
}

那么当你去设置根文档对象的innerHTML时,改用上面的函数。

if(xhr.readyState === XMLHttpRequest.DONE){
    setInnerHtml(document.documentElement, this.responseText);
}

【讨论】:

  • 请问为什么要在script标签中添加name和value属性?另外,if 语句中的单个等号是一个诚实的错误,我确实在我的项目中写了 3 个等号。
  • 抱歉回复晚了,现在才注意到你的评论。但是脚本标签可以包含诸如“crossorigin”、“integrity”等属性。您可以在此处查看有关脚本这些属性的使用的更多信息:developer.mozilla.org/en-US/docs/Web/HTML/Element/script。尽管在您的简单示例中,文本文件中的脚本标记不包含属性,但我认为添加处理该问题的代码是一种好习惯。
【解决方案2】:

我发现通过创建一个脚本元素并将其源设置为“another-file.js”这样的工作:

var script = document.createElement("script");
script.src = "test.js";
document.body.appendChild(script);
THIS GOES AFTER document.documentElement.innerHTML = this.responseText;

【讨论】:

    猜你喜欢
    • 2014-04-26
    • 2013-03-10
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 2021-10-12
    相关资源
    最近更新 更多