【问题标题】:How do you execute a dynamically loaded JavaScript block?如何执行动态加载的 JavaScript 块?
【发布时间】:2008-09-16 19:20:45
【问题描述】:

我正在一个网页上进行 AJAX 调用,该调用返回一大段 HTML,例如:

<div>
  <!-- some html -->
  <script type="text/javascript">
    /** some javascript */
  </script>
</div>

我将整个内容插入到 DOM 中,但 JavaScript 没有运行。有没有办法运行它?

一些细节:我无法控制脚本块中的内容(所以我无法将其更改为可以调用的函数),我只需要执行整个块。我无法在响应上调用 eval,因为 JavaScript 位于更大的 HTML 块中。我可以做某种正则表达式来分离 JavaScript,然后在其上调用 eval,但这很糟糕。有人知道更好的方法吗?

【问题讨论】:

  • 迄今为止我发现的最好的answer。我相信它适用于大多数情况。

标签: javascript ajax


【解决方案1】:

通过设置元素的 innerHTML 属性添加的脚本不会被执行。尝试创建一个新的 div,设置它的 innerHTML,然后将这个新的 div 添加到 DOM。例如:

函数 addScript() { var str = "
正文>
【解决方案2】:

如果您使用响应来填充 div 或其他内容,则不必使用正则表达式。您可以使用 getElementsByTagName。

div.innerHTML = response;
var scripts = div.getElementsByTagName('script');
for (var ix = 0; ix < scripts.length; ix++) {
    eval(scripts[ix].text);
}

【讨论】:

    【解决方案3】:

    虽然接受了@Ed 的回答。不适用于当前版本的 Firefox、Google Chrome 或 Safari 浏览器我设法熟练他的示例以便调用动态添加的脚本。

    仅在将脚本添加到 DOM 的方式上进行必要的更改。与其将其添加为innerHTML,不如将​​其添加为innerHTML,而是创建一个新的脚本元素并将实际脚本内容作为innerHTML 添加到创建的元素,然后将脚本元素附加到实际目标。

    <html>
    <head>
    <script type='text/javascript'>
    function addScript()
    {
        var newdiv = document.createElement('div');
    
        var p = document.createElement('p');
        p.innerHTML = "Dynamically added text";
        newdiv.appendChild(p);
    
        var script = document.createElement('script');
        script.innerHTML = "alert('i am here');";
        newdiv.appendChild(script);
    
        document.getElementById('target').appendChild(newdiv);
    }
    </script>
    </head>
    <body>
    <input type="button" value="add script" onclick="addScript()"/>
    <div>hello world</div>
    <div id="target"></div>
    </body>
    </html>
    

    这适用于 Firefox 42、Google Chrome 48 和 Safari 9.0.3

    【讨论】:

      【解决方案4】:

      另一种方法是不只是使用 InnerHTML 将 Ajax 调用的返回值转储到 DOM 中。

      您可以动态插入每个节点,然后脚本就会运行。

      否则,浏览器只会假定您正在插入一个文本节点,而忽略脚本。

      使用 Eval 相当邪恶,因为它需要启动另一个 Javascript VM 实例并 JIT 传递的字符串。

      【讨论】:

      • 如果能解释一下如何动态插入每个节点就好了。
      【解决方案5】:

      最好的方法可能是直接通过 DOM 识别和评估脚本块的内容。

      不过我会小心.. 如果您实施此操作是为了克服一些场外呼叫的限制,那么您就是在打开一个安全漏洞。

      你实现的任何东西都可能被用于 XSS。

      【讨论】:

      • 如果我错了,请纠正我,但我理解这种情况下的 XSS 漏洞的方式,只有当您担心有人能够访问其他人的在线帐户时才会出现问题,因此能够窃取敏感信息,但如果用户无法登录该站点,则不必担心。
      【解决方案6】:

      您可以使用一种流行的 Ajax 库来为您完成此工作。我喜欢Prototype。您可以将 evalScripts:true 添加为 Ajax 调用的一部分,它会自动发生。

      【讨论】:

        【解决方案7】:

        对于那些喜欢危险生活的人:

        // This is the HTML with script element(s) we want to inject
        var newHtml = '<b>After!</b>\r\n<' +
          'script>\r\nchangeColorEverySecond();\r\n</' +
          'script>';
          
        // Here, we separate the script tags from the non-script HTML
        var parts = separateScriptElementsFromHtml(newHtml);
        
        function separateScriptElementsFromHtml(fullHtmlString) {
            var inner = [], outer = [], m;
            while (m = /<script>([^<]*)<\/script>/gi.exec(fullHtmlString)) {
                outer.push(fullHtmlString.substr(0, m.index));
                inner.push(m[1]);
                fullHtmlString = fullHtmlString.substr(m.index + m[0].length);
            }
            outer.push(fullHtmlString);
            return {
                html: outer.join('\r\n'),
                js: inner.join('\r\n')
            };
        }
        
        // In 2 seconds, inject the new HTML, and run the JS
        setTimeout(function(){
          document.getElementsByTagName('P')[0].innerHTML = parts.html;
          eval(parts.js);
        }, 2000);
        
        
        // This is the function inside the script tag
        function changeColorEverySecond() {
          document.getElementsByTagName('p')[0].style.color = getRandomColor();
          setTimeout(changeColorEverySecond, 1000);
        }
        
        // Here is a fun fun function copied from:
        // https://stackoverflow.com/a/1484514/2413712
        function getRandomColor() {
          var letters = '0123456789ABCDEF';
          var color = '#';
          for (var i = 0; i < 6; i++) {
            color += letters[Math.floor(Math.random() * 16)];
          }
          return color;
        }
        &lt;p&gt;Before&lt;/p&gt;

        【讨论】:

        • “危险地生活”...由于使用了exec
        猜你喜欢
        • 2014-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-18
        • 1970-01-01
        • 1970-01-01
        • 2015-01-11
        相关资源
        最近更新 更多