【问题标题】:Can scripts be inserted with innerHTML?可以用 innerHTML 插入脚本吗?
【发布时间】:2010-11-14 22:00:40
【问题描述】:

我尝试在<div> 上使用innerHTML 将一些脚本加载到页面中。脚本似乎加载到 DOM 中,但从未执行(至少在 Firefox 和 Chrome 中)。有没有办法在使用innerHTML 插入脚本时执行脚本?

示例代码:

<!DOCTYPE html>
<html>
  <body onload="document.getElementById('loader').innerHTML = '<script>alert(\'hi\')<\/script>'">
    Shouldn't an alert saying 'hi' appear?
    <div id="loader"></div>
  </body>
</html>

【问题讨论】:

    标签: javascript html dom innerhtml


    【解决方案1】:

    您必须使用 eval() 来执行您作为 DOM 文本插入的任何脚本代码。

    MooTools 会自动为您执行此操作,我相信 jQuery 也会这样做(取决于版本。jQuery 版本 1.6+ 使用 eval)。这省去了解析&lt;script&gt; 标签和转义您的内容以及一堆其他“陷阱”的麻烦。

    通常,如果您要自己去eval(),您希望创建/发送不带任何 HTML 标记(例如 &lt;script&gt;)的脚本代码,因为这些不会正确地 eval()

    【讨论】:

    • 我真正想做的是加载一个外部脚本,而不仅仅是评估一些本地脚本。使用 innerHTML 添加脚本标记比创建脚本 DOM 元素并将其添加到正文要短得多,我正在尝试使我的代码尽可能短。您是否必须创建 dom 脚本元素并将它们添加到 dom 中,而不仅仅是使用像 innerHTML 这样的东西?有没有办法在函数中使用 document.write 来做到这一点?
    • 正如 zombat 建议的那样,使用 Javascript 框架来加载外部脚本,不要试图重新发明轮子。 JQuery 使这非常容易,只需包含 JQuery 并调用:$.getScript(url)。您还可以提供一个回调函数,该函数将在脚本加载后执行。
    • 爱丽儿是对的。我很欣赏尝试使您的代码保持简短,并添加带有innerHTML&lt;script&gt; 标记可能很短,但它不起作用。在通过eval() 运行之前,这一切都只是纯文本。可悲的是,eval() 不解析 HTML 标签,所以你最终会遇到一系列问题。
    • eval() 不是解决任何问题的好方法。
    • 我自己试过 eval()。这是一个可怕的想法。你必须评估整个事情每次。即使您声明了一个变量名和值,您也必须每次重新声明/重新评估()它才能使其工作。这是一场错误的噩梦。
    【解决方案2】:

    这是一种递归地用可执行脚本替换所有脚本的方法:

    function nodeScriptReplace(node) {
            if ( nodeScriptIs(node) === true ) {
                    node.parentNode.replaceChild( nodeScriptClone(node) , node );
            }
            else {
                    var i = -1, children = node.childNodes;
                    while ( ++i < children.length ) {
                          nodeScriptReplace( children[i] );
                    }
            }
    
            return node;
    }
    function nodeScriptClone(node){
            var script  = document.createElement("script");
            script.text = node.innerHTML;
    
            var i = -1, attrs = node.attributes, attr;
            while ( ++i < attrs.length ) {                                    
                  script.setAttribute( (attr = attrs[i]).name, attr.value );
            }
            return script;
    }
    
    function nodeScriptIs(node) {
            return node.tagName === 'SCRIPT';
    }
    

    调用示例:

    nodeScriptReplace(document.getElementsByTagName("body")[0]);
    

    【讨论】:

    • 我有点惊讶你的回答一直都在下降。恕我直言,这是最好的解决方案,这种方法甚至可以让您限制具有特定 url 或内容的脚本。
    • [0]的目的是什么?你能用 nodeScriptReplace(document.getElementById().html);
    • 这太神奇了。完美运行
    • 很棒的解决方案,谢谢 :) 如果有人正在寻找更现代的版本:stackoverflow.com/a/69190644/1343851
    • 这太棒了。谢谢。
    【解决方案3】:

    这是一个非常有趣的解决您的问题的方法: http://24ways.org/2005/have-your-dom-and-script-it-too

    所以用这个代替脚本标签:

    &lt;img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" /&gt;

    【讨论】:

    • 当插入到 ajax 请求的结果中时对我不起作用:缺少语法错误;脚本字符串开头的 before 语句
    • 你们如何将 <img src... 行添加到您的页面代码中?你是 document.write() 还是使用 document.body.innerHTML+= 方法?两者对我来说都失败了:(
    • onload 属性中编写大量代码不太实用。这也需要一个额外的文件存在并被加载。 momo's solution 不是妥协。
    • 两个缺点:1.它不能调用通过innerHTML(连同这个IMG标签)添加的任何脚本/函数,因为它们在浏览器中不存在2.如果部分内联代码在 ".removeChild()" 抛出异常之前,不会删除 img 元素。
    • 您可以 Base64 将您的触发图像编码为 &lt;img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"&gt;(这不会执行网络请求)实际上...您不需要图像,引用不存在的图像而不是 @ 987654326@ 使用onerror (但这会做一个网络请求)
    【解决方案4】:

    您可以创建脚本,然后注入内容。

    var g = document.createElement('script');
    var s = document.getElementsByTagName('script')[0];
    g.text = "alert(\"hi\");"
    s.parentNode.insertBefore(g, s);
    

    这适用于所有浏览器:)

    【讨论】:

    • 除非文档中没有任何其他脚本元素。请改用document.documentElement
    • 没有必要,因为您正在从另一个脚本编写脚本。 &lt;script&gt;var g = document.createElement('script');var s = document.getElementsByTagName('script')[0]; //reference this scriptg.text = "alert(\"hi\");"s.parentNode.insertBefore(g, s);&lt;/script&gt;
    • 谁说它来自另一个脚本?您可以在没有 &lt;script&gt; 元素的情况下运行 JavaScript。例如。 &lt;img onerror="..." src="#"&gt;&lt;body onload="..."&gt;。如果您想成为技术人员,由于不明确的命名空间,这在非 HTML/SVG 文档中也不起作用。
    • Facebook 在他们的 SDK 中使用了 Pablo 的答案。 developers.facebook.com/docs/javascript/quickstart/v2.2#loading
    【解决方案5】:

    我使用了这个代码,它工作正常

    var arr = MyDiv.getElementsByTagName('script')
    for (var n = 0; n < arr.length; n++)
        eval(arr[n].innerHTML)//run script inside div
    

    【讨论】:

    • 谢谢。它解决了我将 Disqus 通用代码添加到使用 TinyBox2 Jquery 插件创建的模式弹出窗口的问题。
    • 不幸的是,当脚本包含稍后将调用的函数时,此解决方案不起作用。
    【解决方案6】:

    我在使用 innerHTML 时遇到了这个问题,我不得不将一个 Hotjar 脚本附加到我的 Reactjs 应用程序的“head”标签中,并且它必须在附加后立即执行。

    动态 Node 导入到“head”标签的一个很好的解决方案是React-helment 模块。


    此外,对于提议的问题,还有一个有用的解决方案:

    innerHTML 中没有脚本标签!

    事实证明,HTML5 不允许使用 innerHTML 属性动态添加脚本标签。所以下面的代码不会执行,不会有提示说 Hello World!

    element.innerHTML = "<script>alert('Hello World!')</script>";
    

    这在 HTML5 规范中有记录:

    注意:使用 innerHTML 插入的脚本元素在以下情况下不会执行 它们被插入。

    但请注意,这并不意味着 innerHTML 不受跨站点脚本的影响。可以通过innerHTML 执行JavaScript,而无需使用MDN's innerHTML page 所示的标签。

    解决方案:动态添加脚本

    要动态添加脚本标签,您需要创建一个新的脚本元素并将其附加到目标元素。

    您可以对外部脚本执行此操作:

    var newScript = document.createElement("script");
    newScript.src = "http://www.example.com/my-script.js";
    target.appendChild(newScript);
    

    和内联脚本:

    var newScript = document.createElement("script");
    var inlineScript = document.createTextNode("alert('Hello World!');");
    newScript.appendChild(inlineScript); 
    target.appendChild(newScript);
    

    【讨论】:

    • 您的newScript 元素具有HTMLScriptElement interface,因此您只需使用newScript.text = "alert('Hello World!')"; 设置内联代码,无需创建和附加新的文本节点。
    • @Martin 当然,在编程世界中有很多不同的方式来实现东西!这也更清晰和可维护:)。
    【解决方案7】:

    每次我想动态插入脚本标签时我都会这样做!

      const html =
        `<script>
            alert('? there ! Wanna grab a ?'); 
        </script>`;
    
      const scriptEl = document.createRange().createContextualFragment(html);
      parent.append(scriptEl);
    

    注意:使用 ES6

    编辑 1: 为你们澄清 - 我看到很多答案都使用 appendChild 并想让你们知道它与 append 完全一样工作

    【讨论】:

    • 你可以使用这个不错的 react 组件 - github.com/christo-pr/dangerously-set-html-content
    • 这很完美,很容易成为这里最简单的解决方案。我不明白为什么它的票数不高。
    • 它是一个相对较新的旧问题解决方案:P
    【解决方案8】:

    你可以这样做:

    var mydiv = document.getElementById("mydiv");
    var content = "<script>alert(\"hi\");<\/script>";
    
    mydiv.innerHTML = content;
    var scripts = mydiv.getElementsByTagName("script");
    for (var i = 0; i < scripts.length; i++) {
        eval(scripts[i].innerText);
    }
    

    【讨论】:

      【解决方案9】:

      这里的解决方案不使用eval,并且适用于scriptslinked scripts,以及modules

      该函数接受3个参数:

      • html : 要插入的 html 代码字符串
      • dest : 对目标元素的引用
      • append : 允许在目标元素 html 末尾追加的布尔标志
      function insertHTML(html, dest, append=false){
          // if no append is requested, clear the target element
          if(!append) dest.innerHTML = '';
          // create a temporary container and insert provided HTML code
          let container = document.createElement('div');
          container.innerHTML = html;
          // cache a reference to all the scripts in the container
          let scripts = container.querySelectorAll('script');
          // get all child elements and clone them in the target element
          let nodes = container.childNodes;
          for( let i=0; i< nodes.length; i++) dest.appendChild( nodes[i].cloneNode(true) );
          // force the found scripts to execute...
          for( let i=0; i< scripts.length; i++){
              let script = document.createElement('script');
              script.type = scripts[i].type || 'text/javascript';
              if( scripts[i].hasAttribute('src') ) script.src = scripts[i].src;
              script.innerHTML = scripts[i].innerHTML;
              document.head.appendChild(script);
              document.head.removeChild(script);
          }
          // done!
          return true;
      }
      

      【讨论】:

      • 我的意思是......在脚本标签中附加代码内容是一个评估,不是吗?
      • @KevinB 有明显的不同...试试eval('console.log(this)'),你会看到最明显的一个
      • 所以上下文不同,而且?它仍然只是一个评估。
      • @KevinB 不,这不是评估。试试这个eval('let b=100') .. 然后尝试从评估外部访问b .... 祝你好运,你会需要它
      • 为我工作。干杯
      【解决方案10】:

      对于仍在尝试执行此操作的任何人,不,您不能使用innerHTML 注入脚本,但可以使用BlobURL.createObjectURL 将字符串加载到脚本标记中。

      我创建了一个示例,让您可以将字符串作为脚本运行并获取通过承诺返回的脚本的“导出”:

      function loadScript(scriptContent, moduleId) {
          // create the script tag
          var scriptElement = document.createElement('SCRIPT');
      
          // create a promise which will resolve to the script's 'exports'
          // (i.e., the value returned by the script)
          var promise = new Promise(function(resolve) {
              scriptElement.onload = function() {
                  var exports = window["__loadScript_exports_" + moduleId];
                  delete window["__loadScript_exports_" + moduleId];
                  resolve(exports);
              }
          });
      
          // wrap the script contents to expose exports through a special property
          // the promise will access the exports this way
          var wrappedScriptContent =
              "(function() { window['__loadScript_exports_" + moduleId + "'] = " + 
              scriptContent + "})()";
      
          // create a blob from the wrapped script content
          var scriptBlob = new Blob([wrappedScriptContent], {type: 'text/javascript'});
      
          // set the id attribute
          scriptElement.id = "__loadScript_module_" + moduleId;
      
          // set the src attribute to the blob's object url 
          // (this is the part that makes it work)
          scriptElement.src = URL.createObjectURL(scriptBlob);
      
          // append the script element
          document.body.appendChild(scriptElement);
      
          // return the promise, which will resolve to the script's exports
          return promise;
      }
      
      ...
      
      function doTheThing() {
          // no evals
          loadScript('5 + 5').then(function(exports) {
               // should log 10
              console.log(exports)
          });
      }
      

      我已经从我的实际实现中简化了这一点,所以没有承诺其中没有任何错误。但原理是有效的。

      如果您不关心在脚本运行后取回任何值,那就更容易了;只需省略 Promiseonload 位。您甚至不需要包装脚本或创建全局 window.__load_script_exports_ 属性。

      【讨论】:

      • 我刚试过,它适用于 chrome 57。脚本标签上的 innerHTML 执行文本。
      • 这很有趣,它以前不起作用。我想知道这种行为是跨浏览器还是仅在 chrome 57 中。
      【解决方案11】:

      这是一个递归函数,用于设置我在广告服务器中使用的元素的 innerHTML:

      // o: container to set the innerHTML
      // html: html text to set.
      // clear: if true, the container is cleared first (children removed)
      function setHTML(o, html, clear) {
          if (clear) o.innerHTML = "";
      
          // Generate a parseable object with the html:
          var dv = document.createElement("div");
          dv.innerHTML = html;
      
          // Handle edge case where innerHTML contains no tags, just text:
          if (dv.children.length===0){ o.innerHTML = html; return; }
      
          for (var i = 0; i < dv.children.length; i++) {
              var c = dv.children[i];
      
              // n: new node with the same type as c
              var n = document.createElement(c.nodeName);
      
              // copy all attributes from c to n
              for (var j = 0; j < c.attributes.length; j++)
                  n.setAttribute(c.attributes[j].nodeName, c.attributes[j].nodeValue);
      
              // If current node is a leaf, just copy the appropriate property (text or innerHTML)
              if (c.children.length == 0)
              {
                  switch (c.nodeName)
                  {
                      case "SCRIPT":
                          if (c.text) n.text = c.text;
                          break;
                      default:
                          if (c.innerHTML) n.innerHTML = c.innerHTML;
                          break;
                  }
              }
              // If current node has sub nodes, call itself recursively:
              else setHTML(n, c.innerHTML, false);
              o.appendChild(n);
          }
      }
      

      你可以看演示here

      【讨论】:

        【解决方案12】:

        是的,你可以,但你必须在 DOM 之外进行,并且顺序必须正确。

        var scr = '<scr'+'ipt>alert("foo")</scr'+'ipt>';
        window.onload = function(){
            var n = document.createElement("div");
            n.innerHTML = scr;
            document.body.appendChild(n);
        }
        

        ...会提醒'foo'。这行不通:

        document.getElementById("myDiv").innerHTML = scr;
        

        即使这样也行不通,因为节点是先插入的:

        var scr = '<scr'+'ipt>alert("foo")</scr'+'ipt>';
        window.onload = function(){
            var n = document.createElement("div");
            document.body.appendChild(n);
            n.innerHTML = scr;  
        }
        

        【讨论】:

        • 对于它的价值:这似乎不适用于当前的浏览器。
        【解决方案13】:

        Krasimir Tsonev 有一个很好的解决方案,可以克服所有问题。 他的方法不需要使用eval,所以不存在性能和安全问题。 它允许您设置 innerHTML 字符串包含带有 js 的 html 并立即将其转换为 DOM 元素,同时还可以执行代码中存在的 js 部分。简短,简单,完全按照您的意愿工作。

        享受他的解决方案:

        http://krasimirtsonev.com/blog/article/Convert-HTML-string-to-DOM-element

        重要提示:

        1. 你需要用div标签包裹目标元素
        2. 你需要用div标签包裹src字符串。
        3. 如果你直接写src字符串并且它包含js部分,请注意正确写结束脚本标签(在/之前带有\),因为这是一个字符串。

        【讨论】:

          【解决方案14】:

          过滤您的脚本标签并使用 eval 运行每个标签

          var tmp=  document.createElement('div');
          tmp.innerHTML = '<script>alert("hello")></script>';
          [...tmp.children].filter(x => x.nodeName === 'SCRIPT').forEach(x => eval(x.innerText));
          

          【讨论】:

            【解决方案15】:

            使用$(parent).html(code) 而不是parent.innerHTML = code

            以下内容还修复了使用document.write 的脚本和通过src 属性加载的脚本。不幸的是,即使这也不适用于 Google AdSense 脚本。

            var oldDocumentWrite = document.write;
            var oldDocumentWriteln = document.writeln;
            try {
                document.write = function(code) {
                    $(parent).append(code);
                }
                document.writeln = function(code) {
                    document.write(code + "<br/>");
                }
                $(parent).html(html); 
            } finally {
                $(window).load(function() {
                    document.write = oldDocumentWrite
                    document.writeln = oldDocumentWriteln
                })
            }
            

            Source

            【讨论】:

            • 这里有点晚了,但是任何可能使用此方法的人,请注意在 JQuery 中您需要使用 $.loadScript(url) 而不是
            【解决方案16】:

            尝试使用模板和 document.importNode。这是一个例子:

            <!DOCTYPE html>
            <html>
            <head>
            <meta charset="UTF-8">
            <title>Sample</title>
            </head>
            <body>
            <h1 id="hello_world">Sample</h1>
            <script type="text/javascript">
             var div = document.createElement("div");
              var t = document.createElement('template');
              t.innerHTML =  "Check Console tab for javascript output: Hello world!!!<br/><script type='text/javascript' >console.log('Hello world!!!');<\/script>";
              
              for (var i=0; i < t.content.childNodes.length; i++){
                var node = document.importNode(t.content.childNodes[i], true);
                div.appendChild(node);
              }
             document.body.appendChild(div);
            </script>
             
            </body>
            </html>

            【讨论】:

            • 这不适用于 Microsoft Edge,还有其他解决方法吗?
            【解决方案17】:

            你也可以像这样包装你的&lt;script&gt;,它会被执行:

            <your target node>.innerHTML = '<iframe srcdoc="<script>alert(top.document.title);</script>"></iframe>';
            

            请注意:srcdoc 中的作用域指的是 iframe,因此您必须像上例一样使用top 来访问父文档。

            【讨论】:

              【解决方案18】:

              这是mmm's awesome solution 的更现代(更简洁)的版本:

              function executeScriptElements(containerElement) {
                const scriptElements = containerElement.querySelectorAll("script");
              
                Array.from(scriptElements).forEach((scriptElement) => {
                  const clonedElement = document.createElement("script");
              
                  Array.from(scriptElement.attributes).forEach((attribute) => {
                    clonedElement.setAttribute(attribute.name, attribute.value);
                  });
                  
                  clonedElement.text = scriptElement.text;
              
                  scriptElement.parentNode.replaceChild(clonedElement, scriptElement);
                });
              }
              

              注意:我也尝试过使用 cloneNode()outerHTML 的替代解决方案,但没有奏效。

              【讨论】:

                【解决方案19】:

                我对这个问题的解决方案是设置一个Mutation Observer 来检测&lt;script&gt;&lt;/script&gt; 节点,然后将其替换为具有相同src 的新&lt;script&gt;&lt;/script&gt; 节点。例如:

                let parentNode = /* node to observe */ void 0
                let observer = new MutationObserver(mutations=>{
                    mutations.map(mutation=>{
                        Array.from(mutation.addedNodes).map(node=>{
                            if ( node.parentNode == parentNode ) {
                                let scripts = node.getElementsByTagName('script')
                                Array.from(scripts).map(script=>{
                                    let src = script.src
                                    script = document.createElement('script')
                                    script.src = src
                                    return script
                                })
                            }
                        })
                    })
                })
                observer.observe(document.body, {childList: true, subtree: true});
                

                【讨论】:

                • 感谢您在不说明原因的情况下对我投反对票。爱你们。
                • 解释:这个sn-p(直接添加到HTML)确保任何将来添加为innerHTML的外部脚本都将被解析。我发现这是一个很好的通用想法,但我没有赞成,因为担心document.createElement 添加的脚本是否可能被执行两次?改变变异对象也让我害怕——我不确定它在某些情况下是否不能产生无限循环。
                【解决方案20】:

                Gabriel Garcia 提到的 MutationObservers 是在正确的轨道上,但对我来说并不是很有效。我不确定这是因为浏览器的怪癖还是由于我的错误,但最终为我工作的版本如下:

                document.addEventListener("DOMContentLoaded", function(event) {
                    var observer = new MutationObserver(mutations=>{
                        mutations.map(mutation=>{
                            Array.from(mutation.addedNodes).map(node=>{
                                if (node.tagName === "SCRIPT") {
                                    var s = document.createElement("script");
                                    s.text=node.text;
                                    if (typeof(node.parentElement.added) === 'undefined')
                                        node.parentElement.added = [];
                                    node.parentElement.added[node.parentElement.added.length] = s;
                                    node.parentElement.removeChild(node);
                                    document.head.appendChild(s);
                                }
                            })
                        })
                    })
                    observer.observe(document.getElementById("element_to_watch"), {childList: true, subtree: true,attributes: false});
                };
                

                当然,您应该将element_to_watch 替换为正在修改的元素的名称。

                node.parentElement.added 用于存储添加到document.head 的脚本标签。在用于加载外部页面的函数中,您可以使用以下内容删除不再相关的脚本标签:

                function freeScripts(node){
                    if (node === null)
                        return;
                    if (typeof(node.added) === 'object') {
                        for (var script in node.added) {
                            document.head.removeChild(node.added[script]);
                        }
                        node.added = {};
                    }
                    for (var child in node.children) {
                        freeScripts(node.children[child]);
                    }
                }
                

                还有一个加载函数开头的例子:

                function load(url, id, replace) {
                    if (document.getElementById(id) === null) {
                        console.error("Element of ID "+id + " does not exist!");
                        return;
                    }
                    freeScripts(document.getElementById(id));
                    var xhttp = new XMLHttpRequest();
                    // proceed to load in the page and modify innerHTML
                }
                

                【讨论】:

                • 您确实注意到,每次将元素附加到文档时,您都会添加一个新的MutationObserver,对吗?顺便说一句,我想知道你为什么说我的代码不起作用。
                • @gabrielgarcia 我说你的代码不起作用,因为我试过了,但它根本不起作用。现在看,完全有可能是我,而不是你,我真诚地为我的措辞道歉。现在修复它。
                • re: 每次向文档中添加元素时添加一个MutationObserver,你在说什么? DOMContentLoaded,我在这里引用 MDN,“在初始 HTML 文档完全加载和解析时触发,无需等待样式表、图像和子框架完成加载。”这是一次,而且只有一次。此外,这个脚本在我的网站上运行没有问题,调试显示它只发生一次,所以它在实践中和理论上都是一次。
                • 你是对的......我错过了它。我也很抱歉。
                • @gabrielgarcia 没问题 :)
                【解决方案21】:

                基于Danny '365CSI' Engelman 的评论,这是一个通用的解决方案:

                <script>
                  alert("This script always runs.");
                  script01 = true;
                </script>
                <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
                 onload="if(typeof script01==='undefined') eval(this.previousElementSibling.innerHTML)">
                

                使用它作为innerHTML(即由XMLHttpRequest加载)或直接(即由PHP后端插入),脚本总是加载一次。

                说明:作为 innerHTML 加载的脚本不会被执行,但 onload 内容属性会被执行。如果脚本未执行(添加为 innerHTML),则在图像 onload 事件中执行脚本。如果脚本已加载(由后端添加),则定义了 script01 变量,并且 onload 将不会第二次运行脚本。

                【讨论】:

                • tnx,这是 2016 年的答案。我现在会这样做:&lt;img src="data:image/svg+xml,&lt;svg xmlns='http://www.w3.org/2000/svg'/&gt;" onload="console.log(21,this)"/&gt;
                【解决方案22】:

                我自己的转折,使用现代 JS 和 typescript。当querySelector 就在那里时,不知道为什么人们在tagName 等上进行过滤。

                对我很有魅力:

                function makeScriptsExecutable(el: Element) {
                  el.querySelectorAll("script").forEach(script => {
                    const clone = document.createElement("script")
                
                    for (const attr of script.attributes) {
                      clone.setAttribute(attr.name, attr.value)
                    }
                
                    clone.text = script.innerHTML
                    script.parentNode?.replaceChild(clone, script)
                  })
                }
                

                【讨论】:

                  【解决方案23】:

                  从 innerHTML 执行(Java 脚本)标签

                  将您的脚本元素替换为具有类属性 class="javascript" 的 div 并用 &lt;/div&gt; 关闭它

                  不要更改要执行的内容(以前在 script 标签中,现在在 div 标签中)

                  在页面中添加样式...

                  &lt;style type="text/css"&gt; .javascript { display: none; } &lt;/style&gt;

                  现在使用 jquery 运行 eval(jquery js 应该已经包含)

                     $('.javascript').each(function() {
                        eval($(this).text());
                  
                      });`
                  

                  您可以在我的博客上探索更多here

                  【讨论】:

                    【解决方案24】:

                    对我来说最好的办法是通过innerHtml插入新的HTML内容,然后使用

                    setTimeout(() => {
                            var script_el = document.createElement("script")
                            script_el.src = 'script-to-add.js'
                            document.body.appendChild(script_el)
                        }, 500)
                    

                    setTimeout 不是必需的,但效果更好。这对我有用。

                    【讨论】:

                      猜你喜欢
                      相关资源
                      最近更新 更多