Ausführen von mit .innerHTML eingefügten <script> -Elementen

111

Ich habe ein Skript, das mithilfe von Inhalten Inhalte in ein Element einfügt innerHTML.

Der Inhalt könnte zum Beispiel sein:

<script type="text/javascript">alert('test');</script>
<strong>test</strong>

Das Problem ist, dass der Code im <script>Tag nicht ausgeführt wird. Ich habe ein bisschen gegoogelt, aber es gab keine offensichtlichen Lösungen. Wenn ich den Inhalt mit jQuery eingefügt habe, wurden $(element).append(content);die Skriptteile evalvor dem Einfügen in das DOM erstellt.

Hat jemand einen Codeausschnitt, der alle <script>Elemente ausführt ? Der jQuery-Code war etwas komplex, so dass ich nicht wirklich herausfinden konnte, wie es gemacht wurde.

Bearbeiten :

Durch einen Blick in den jQuery-Code konnte ich herausfinden, wie jQuery dies tut, was zu folgendem Code führte:

Demo:
<div id="element"></div>

<script type="text/javascript">
  function insertAndExecute(id, text)
  {
    domelement = document.getElementById(id);
    domelement.innerHTML = text;
    var scripts = [];

    ret = domelement.childNodes;
    for ( var i = 0; ret[i]; i++ ) {
      if ( scripts && nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
            scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
        }
    }

    for(script in scripts)
    {
      evalScript(scripts[script]);
    }
  }
  function nodeName( elem, name ) {
    return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
  }
  function evalScript( elem ) {
    data = ( elem.text || elem.textContent || elem.innerHTML || "" );

    var head = document.getElementsByTagName("head")[0] || document.documentElement,
    script = document.createElement("script");
    script.type = "text/javascript";
    script.appendChild( document.createTextNode( data ) );
    head.insertBefore( script, head.firstChild );
    head.removeChild( script );

    if ( elem.parentNode ) {
        elem.parentNode.removeChild( elem );
    }
  }

  insertAndExecute("element", "<scri"+"pt type='text/javascript'>document.write('This text should appear as well.')</scr"+"ipt><strong>this text should also be inserted.</strong>");
</script>
Phidah
quelle
1
Warum können Sie nicht einfach die untergeordneten Elemente des Elements iterieren und für jedes Element, das ein Skriptelement ist, nur das innere HTML dieses untergeordneten Elements auswerten ()? So habe ich es von einem großen Komponentenhersteller gesehen, jedes Mal, wenn er einen Ajax-Rückruf durchführt, der dem DOM Dinge hinzufügt, tun sie genau das. Bedenken Sie jedoch, dass es langsam sein kann, insbesondere in IE7.
Slugster
2
Andreas: Wenn ich eine Funktion hinzufüge, zum Beispiel function testFunction(){ alert('test'); }zu dem in innerHTML eingefügten Code, und dann versuche, sie aufzurufen, heißt es, dass die Funktion nicht definiert ist.
Phidah
1
Ehrfürchtige Phidah, wirkt wie Charme, Prost
Marcin
3
Ich denke, es ist absolut wichtig zu verstehen, dass dies ein beabsichtigtes Verhalten des Browsers ist, um Cross-Site-Scripting-Angriffe zu verhindern. Wenn der von Ihnen als innerHTML festgelegte Text von Bob bereitgestellt wird, wird er in Alices Browser ausgeführt und verursacht Schaden (stellen Sie sich ein Forum vor, in dem Benutzer Kommentare schreiben können, die ihnen Skript-Tags hinzufügen). Sie können hier mehr darüber lesen: en.wikipedia.org/wiki/Cross-site_scripting . Bleib sicher!
Xatian
1
Ein HTML hat sich seit 2010 stark verändert. In diesen Tagen möchten Sie vielleicht einen Blick darauf werfen: stackoverflow.com/a/58862506/890357
marciowb

Antworten:

27

Das Skript des OP funktioniert in IE 7 nicht. Mit Hilfe von SO ist hier ein Skript, das Folgendes tut:

exec_body_scripts: function(body_el) {
  // Finds and executes scripts in a newly added element's body.
  // Needed since innerHTML does not run scripts.
  //
  // Argument body_el is an element in the dom.

  function nodeName(elem, name) {
    return elem.nodeName && elem.nodeName.toUpperCase() ===
              name.toUpperCase();
  };

  function evalScript(elem) {
    var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
        head = document.getElementsByTagName("head")[0] ||
                  document.documentElement,
        script = document.createElement("script");

    script.type = "text/javascript";
    try {
      // doesn't work on ie...
      script.appendChild(document.createTextNode(data));      
    } catch(e) {
      // IE has funky script nodes
      script.text = data;
    }

    head.insertBefore(script, head.firstChild);
    head.removeChild(script);
  };

  // main section of function
  var scripts = [],
      script,
      children_nodes = body_el.childNodes,
      child,
      i;

  for (i = 0; children_nodes[i]; i++) {
    child = children_nodes[i];
    if (nodeName(child, "script" ) &&
      (!child.type || child.type.toLowerCase() === "text/javascript")) {
          scripts.push(child);
      }
  }

  for (i = 0; scripts[i]; i++) {
    script = scripts[i];
    if (script.parentNode) {script.parentNode.removeChild(script);}
    evalScript(scripts[i]);
  }
};
Larry K.
quelle
4
Verwenden Sie besser jQuery's $(parent).html(code)- siehe meine Antwort unten.
Iirekm
Wie soll ich das Skript entfernen, nachdem es in DOM eingefügt wurde?
S4beR
1
Das Skript ist nicht rekursiv und betrachtet nur direkte untergeordnete Elemente. Das funktioniert bei mir:if (nodeName(child, "script" ) && (!child.type || child.type.toLowerCase() === "text/javascript")) { scripts.push(child); } else { exec_body_scripts(child); }
st4wik
2
Beachten Sie, dass der obige Code keine Skripte ausführt, die über src geladen werden. Das obige Skript kann geändert werden, um elem.srcdie srcEigenschaft des erstellten Skriptelements zu überprüfen und bedingt festzulegen, anstatt dessen Textinhalt festzulegen.
Ryan Morlok
Warum nicht den globalen evalTrick verwenden, anstatt ein <script>Element zu erstellen und es in das einzufügen <head>? Beide führen JS-Code aus, ohne den aktuellen Abschluss verfügbar zu machen.
Finesse
31

@phidah ... Hier ist eine sehr interessante Lösung für Ihr Problem: http://24ways.org/2005/have-your-dom-and-script-it-too

Also würde es stattdessen so aussehen:

<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />

user447963
quelle
2
und noch besser, kein Bild mit "onerror" -Ereignis
erforderlich
11
Sie können verwenden, <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">wenn Sie eine nutzlose http-Anforderung verhindern möchten.
Savas Vedova
1
Liebe es ! (hinzugefügt style="display:none;), um das Symbol für kaputte Bilder zu verbergen
kris
Eigentlich <style>ist es besser als <img>, weil es keine Netzwerkanfrage macht
Becken
23

Hier ist ein kürzeres, effizienteres Skript, das auch für Skripte mit der srcEigenschaft funktioniert :

function insertAndExecute(id, text) {
    document.getElementById(id).innerHTML = text;
    var scripts = Array.prototype.slice.call(document.getElementById(id).getElementsByTagName("script"));
    for (var i = 0; i < scripts.length; i++) {
        if (scripts[i].src != "") {
            var tag = document.createElement("script");
            tag.src = scripts[i].src;
            document.getElementsByTagName("head")[0].appendChild(tag);
        }
        else {
            eval(scripts[i].innerHTML);
        }
    }
}

Hinweis: evalWenn es nicht ordnungsgemäß verwendet wird, kann es zwar zu einer Sicherheitslücke kommen, es ist jedoch viel schneller als das Erstellen eines Skript-Tags im laufenden Betrieb.

DividedByZero
quelle
1
das hat mir geholfen, aber ich fühle mich schmutzig mit eval. Um sicherzustellen, dass Text nicht kompromittiert werden kann, sehe ich keine Sicherheitslücke.
John
@ random-user evalwurde entwickelt, um Benutzer zu verletzen. Jede dynamische Skriptausführung ist ein Risiko, und deshalb ruft CSP sie auf, 'unsafe-eval'weil sie es ist. Sie beeinträchtigen auch die Sicherheit Ihrer Websites, wenn Sie sie in einer Bibliothek verwenden, da sie diese nicht deaktivieren können.
JonathanKingston
Das Testen in Chrome 44 führt beim Aufruf von appendChild zu einer Endlosschleife, da dadurch der Wert scripts.length erhöht wird.
Codewithcheese
4
Skripte mit der srcEigenschaft werden asynchron heruntergeladen und bei Ankunft ausgeführt. Bestellung bleibt nicht erhalten. Inline-Skripte werden auch außerhalb der Reihenfolge synchron vor den asynchronen ausgeführt.
Robert4
21

Sie sollten nicht die innerHTML-Eigenschaft verwenden, sondern die appendChild-Methode des Knotens: einen Knoten in einem Dokumentbaum [HTML DOM]. Auf diese Weise können Sie später Ihren injizierten Code aufrufen.

Stellen Sie sicher, dass Sie verstehen, dass dies node.innerHTML nicht dasselbe ist wie node.appendChild . Möglicherweise möchten Sie einige Zeit in der Javascript-Client-Referenz verbringen, um weitere Informationen und das DOM zu erhalten. Hoffe das Folgende hilft ...

Probeninjektion funktioniert:

<html>
<head>
<title>test</title>
<script language="javascript" type="text/javascript">
    function doOnLoad(){
        addScript('inject',"function foo(){ alert('injected'); }");
    }


    function addScript(inject,code){
        var _in = document.getElementById('inject');
        var scriptNode = document.createElement('script');
        scriptNode.innerHTML = code;
        _in.appendChild(scriptNode);
    }

</script>
</head>
<body onload="doOnLoad();">
    <div id="header">some content</div>
    <div id="inject"></div>
    <input type="button" onclick="foo(); return false;" value="Test Injected" />
</body>
</html>

Grüße,

Andreas
quelle
2
Endlich jemand, der eher ein bisschen über das Problem erklärt als alle anderen try this, look how clever I amAntworten. Verdient eine UV, es hat meine.
RiggsFolly
Dies ist der einfachste Weg, um Javascript-Code zu injizieren, der nach dem Injizieren ausgeführt wird. Ich verstehe nur nicht den Unterschied zwischen dem Hinzufügen mit innerHTML, das nicht ausgeführt wird, und dem obigen Weg mit appendChild, das ausgeführt wird. Ich habe dies erfolgreich verwendet, um eine dynamische Seite mit Skript von Grund auf mit socket.io
wetlip
2
var _in = document.getElementById(inject);, Meiner Ansicht nach.
Ron Burk
21

Vereinfachte ES6-Version von @ joshcomleys Antwort mit einem Beispiel.

Keine JQuery, keine Bibliothek, keine Auswertung, keine DOM-Änderung, nur reines Javascript.

http://plnkr.co/edit/MMegiu?p=preview

var setInnerHTML = function(elm, html) {
  elm.innerHTML = html;
  Array.from(elm.querySelectorAll("script")).forEach( oldScript => {
    const newScript = document.createElement("script");
    Array.from(oldScript.attributes)
      .forEach( attr => newScript.setAttribute(attr.name, attr.value) );
    newScript.appendChild(document.createTextNode(oldScript.innerHTML));
    oldScript.parentNode.replaceChild(newScript, oldScript);
  });
}

Verwendung

$0.innerHTML = HTML;    // does *NOT* run <script> tags in HTML
setInnerHTML($0, HTML); // does run <script> tags in HTML
allenhwkim
quelle
1
Tippfehler: Der Name der Funktion ist setInnerHtmlnichtsetInnerHTML
pery mimon
Beachten Sie, dass in dem verknüpften plnkr der Funktionsname lautet, setInnerHTMLaber setInnerHtmlinnerhalb der runBFunktion aufgerufen wird . Daher funktioniert das Beispiel nicht
Danbars
16

Probieren Sie dieses Snippet aus:

function stripAndExecuteScript(text) {
    var scripts = '';
    var cleaned = text.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
        scripts += arguments[1] + '\n';
        return '';
    });

    if (window.execScript){
        window.execScript(scripts);
    } else {
        var head = document.getElementsByTagName('head')[0];
        var scriptElement = document.createElement('script');
        scriptElement.setAttribute('type', 'text/javascript');
        scriptElement.innerText = scripts;
        head.appendChild(scriptElement);
        head.removeChild(scriptElement);
    }
    return cleaned;
};


var scriptString = '<scrip' + 't + type="text/javascript">alert(\'test\');</scr' + 'ipt><strong>test</strong>';
document.getElementById('element').innerHTML = stripAndExecuteScript(scriptString);
Fantactuka
quelle
Ja, diese Methode funktioniert, aber Sie erhalten Fehler, wenn Sie Kommentare oder console.logs haben. Achten Sie also darauf, dass Sie auch Änderungen vornehmen können, um Module zu berücksichtigen. var modules = [] var clean = text.replace (/ <script ([^>) ] *)> ([\ s \ S] *?) <\ / script> / gi, Funktion (m, Tags, Skript) {if (/type="module"/.test(tags)) {modules.push (script) return} scripts + = script + '\ n' return ''})
zavr
13
function insertHtml(id, html)  
{  
   var ele = document.getElementById(id);  
   ele.innerHTML = html;  
   var codes = ele.getElementsByTagName("script");   
   for(var i=0;i<codes.length;i++)  
   {  
       eval(codes[i].text);  
   }  
}  

Es funktioniert in Chrome in meinem Projekt

Bruce
quelle
Schnell und hübsch. Danke dir.
Jorge Fuentes González
Das ist es! Danke dir.
Floris
7

Eine Lösung ohne "eval":

var setInnerHtml = function(elm, html) {
  elm.innerHTML = html;
  var scripts = elm.getElementsByTagName("script");
  // If we don't clone the results then "scripts"
  // will actually update live as we insert the new
  // tags, and we'll get caught in an endless loop
  var scriptsClone = [];
  for (var i = 0; i < scripts.length; i++) {
    scriptsClone.push(scripts[i]);
  }
  for (var i = 0; i < scriptsClone.length; i++) {
    var currentScript = scriptsClone[i];
    var s = document.createElement("script");
    // Copy all the attributes from the original script
    for (var j = 0; j < currentScript.attributes.length; j++) {
      var a = currentScript.attributes[j];
      s.setAttribute(a.name, a.value);
    }
    s.appendChild(document.createTextNode(currentScript.innerHTML));
    currentScript.parentNode.replaceChild(s, currentScript);
  }
}

Dies klont im Wesentlichen das Skript-Tag und ersetzt dann das blockierte Skript-Tag durch das neu generierte, wodurch die Ausführung ermöglicht wird.

Joshcomley
quelle
3

scriptNode.innerHTML = codefunktionierte nicht für IE. Das einzige, was zu tun ist, ist durch zu ersetzen scriptNode.text = codeund es funktioniert gut

Jorge
quelle
3

Es ist einfacher, jquery zu verwenden, $(parent).html(code)anstatt parent.innerHTML = code:

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
    })
}

Dies funktioniert auch mit Skripten, die document.writeSkripte verwenden und über srcAttribute geladen werden . Leider funktioniert auch dies nicht mit Google AdSense-Skripten.

iirekm
quelle
1
Was lässt Sie sagen, dass es einfacher ist? Es ist nicht noch kürzer. Ich denke immer, dass eine übermäßige Verwendung von jQuery eine schlechte Idee ist.
Manngo
2

Mach einfach:

document.body.innerHTML = document.body.innerHTML + '<img src="../images/loaded.gif" alt="" onload="alert(\'test\');this.parentNode.removeChild(this);" />';
Lambder
quelle
1
sehen aus wie eine geniale Idee
pery mimon
0

Sie können einen Blick auf diesen Beitrag werfen . Der Code könnte folgendermaßen aussehen:

var actualDivToBeUpdated = document.getElementById('test');
var div = document.createElement('div');
div.innerHTML = '<script type="text/javascript">alert("test");<\/script>';
var children = div.childNodes;
actualDivToBeUpdated.innerHTML = '';
for(var i = 0; i < children.length; i++) {
    actualDivToBeUpdated.appendChild(children[i]);
}
Darin Dimitrov
quelle
0

Dank Larrys Skript, das in IE10 perfekt funktioniert hat, habe ich Folgendes verwendet:

$('#' + id)[0].innerHTML = result;
$('#' + id + " script").each(function() { this.text = this.text || $(this).text();} );
AxD
quelle
0

Ausdehnung von Larry. Ich habe es rekursiv gemacht, den gesamten Block und die untergeordneten Knoten zu durchsuchen.
Das Skript ruft jetzt auch externe Skripte auf, die mit dem Parameter src angegeben werden. Skripte werden an den Kopf angehängt, anstatt eingefügt und in der Reihenfolge platziert, in der sie gefunden wurden. So bleiben speziell Bestellskripte erhalten. Und jedes Skript wird synchron ausgeführt, ähnlich wie der Browser das anfängliche Laden des DOMs handhabt. Wenn Sie also einen Skriptblock haben, der jQuery von einem CDN aufruft und dann der nächste Skriptknoten jQuery verwendet ... Kein Problem! Oh, und ich habe die angehängten Skripte mit einer serialisierten ID versehen, die auf dem basiert, was Sie im Tag-Parameter festgelegt haben, damit Sie herausfinden können, was von diesem Skript hinzugefügt wurde.

exec_body_scripts: function(body_el, tag) {
    // Finds and executes scripts in a newly added element's body.
    // Needed since innerHTML does not run scripts.
    //
    // Argument body_el is an element in the dom.

    function nodeName(elem, name) {
        return elem.nodeName && elem.nodeName.toUpperCase() ===
              name.toUpperCase();
    };

    function evalScript(elem, id, callback) {
        var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
            head = document.getElementsByTagName("head")[0] ||
                      document.documentElement;

        var script = document.createElement("script");
        script.type = "text/javascript";
        if (id != '') {
            script.setAttribute('id', id);
        }

        if (elem.src != '') {
            script.src = elem.src;
            head.appendChild(script);
            // Then bind the event to the callback function.
            // There are several events for cross browser compatibility.
            script.onreadystatechange = callback;
            script.onload = callback;
        } else {
            try {
                // doesn't work on ie...
                script.appendChild(document.createTextNode(data));      
            } catch(e) {
                // IE has funky script nodes
                script.text = data;
            }
            head.appendChild(script);
            callback();
        }
    };

    function walk_children(node) {
        var scripts = [],
          script,
          children_nodes = node.childNodes,
          child,
          i;

        if (children_nodes === undefined) return;

        for (i = 0; i<children_nodes.length; i++) {
            child = children_nodes[i];
            if (nodeName(child, "script" ) &&
                (!child.type || child.type.toLowerCase() === "text/javascript")) {
                scripts.push(child);
            } else {
                var new_scripts = walk_children(child);
                for(j=0; j<new_scripts.length; j++) {
                    scripts.push(new_scripts[j]);
                }
            }
        }

        return scripts;
    }

    var i = 0;
    function execute_script(i) {
        script = scripts[i];
        if (script.parentNode) {script.parentNode.removeChild(script);}
        evalScript(scripts[i], tag+"_"+i, function() {
            if (i < scripts.length-1) {
                execute_script(++i);
            }                
        });
    }

    // main section of function
    if (tag === undefined) tag = 'tmp';

    var scripts = walk_children(body_el);

    execute_script(i);
}
BadOPCode
quelle
0

Versuchen Sie dies, es funktioniert für mich auf Chrome, Safari & Firefox:

var script = document.createElement('script');
script.innerHTML = 'console.log("hi")';
document.body.appendChild(script); 
--> logs "hi"

Beachten Sie jedoch, dass das folgende div-verschachtelte Skript NICHT ausgeführt wird:

var script = document.createElement('div');
script.innerHTML = '<script>console.log("hi")</script>';
document.body.appendChild(script);
--> doesn't log anything

Damit ein Skript ausgeführt werden kann, muss es als Knoten erstellt und dann als untergeordnetes Element angehängt werden. Sie können sogar ein Skript in ein zuvor injiziertes div anhängen und es wird ausgeführt (ich bin bereits darauf gestoßen, als ich versucht habe, den Ad-Server-Code zum Laufen zu bringen):

var div = document.createElement('div');
div.id = 'test-id';
document.body.appendChild(div);
var script = document.createElement('script');
script.innerHTML = 'console.log("hi")';
document.getElementById('test-id').appendChild(script);
--> logs "hi"
Trev14
quelle
0

Die Antwort von Lambder ausgeben

document.body.innerHTML = '<img src="../images/loaded.gif" alt="" > onload="alert(\'test\');this.parentNode.removeChild(this);" />';;

Sie können das base64-Image verwenden, um Ihr Skript zu erstellen und zu laden

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2P4//8/AwAI/AL+iF8G4AAAAABJRU5ErkJggg=="
    onload="var script = document.createElement('script');  script.src = './yourCustomScript.js'; parentElement.append(script);" />

Oder wenn Sie eine haben Iframe, können Sie sie stattdessen verwenden

<iframe src='//your-orginal-page.com' style='width:100%;height:100%'
    onload="var script = document.createElement('script');  script.src = './your-coustom-script.js'; parentElement.append(script);"
    frameborder='0'></iframe>
pery mimon
quelle
0

Ich brauchte etwas Ähnliches, aber das Skript musste an derselben Stelle wie das ursprüngliche Skript verbleiben oder neu erstellt werden, da mein Skript auf die Position des Skript-Tags im DOM abzielt, um / Zielelemente zu erstellen. Ich habe das Skript auch rekursiv gemacht, um sicherzustellen, dass es auch funktioniert, wenn es mehr als eine Ebene tiefer liegt.

HINWEIS: Ich verwende consthier, wenn Sie einen älteren Browser haben, verwenden Sie einfach var.

    window.exec_body_scripts = function(body_el) {
        // ref: /programming/2592092/executing-script-elements-inserted-with-innerhtml based on Larry K's answer
        // Finds and executes scripts in a newly added element's body.
        // Needed since innerHTML does not run scripts.
        //
        // Argument body_el is an element in the dom.
        const
            type__Js = 'text/javascript',
            tagName__Script = 'script',
            tagName__Script__Upper = tagName__Script.toUpperCase();
        var scripts = [], script, i;
        function evalScript(elem) {
            var parent = elem.parentNode,
                data = (elem.text || elem.textContent || elem.innerHTML || ""),
                script = document.createElement(tagName__Script);

            script.type = type__Js;
            try {
                // doesn't work on ie...
                script.appendChild(document.createTextNode(data));
            } catch (e) {
                // IE has funky script nodes
                script.text = data;
            }
            // Make sure to re-insert the script at the same position
            // to make sure scripts that target their position
            // in the DOM function as expected.
            var parent = elem.parentNode;
            parent.insertBefore(script, elem);
            parent.removeChild(elem);
        };
        // Get all scripts (recursive)
        if (typeof (document.querySelectorAll) !== typeof (void 0)) {
            document.querySelectorAll('script').forEach((scr) => { if (!scr.type || scr.type.toLowerCase() === type__Js) scripts.push(scr); });
        }
        else {
            var children_nodes = body_el.childNodes, child;
            for (i = 0; children_nodes[i]; i++) {
                child = children_nodes[i];
                if (
                    child.nodeName
                    &&
                    child.nodeName.toUpperCase() === tagName__Script__Upper
                    &&
                    (
                        !child.type
                        ||
                        child.type.toLowerCase() === type__Js
                    )
                ) {
                    scripts.push(child);
                }
                // Recursive call
                window.exec_body_scripts(child);
            }
        }
        for (i = 0; scripts[i]; i++) {
            evalScript(scripts[i]);
        }
    };
NKCSS
quelle
0

Diese neue Hilfsfunktion wurde in TypeScript erstellt. Vielleicht wird es jemand zu schätzen wissen. Wenn Sie die Typdeklaration aus dem Skriptparameter entfernen, handelt es sich nur um einfaches JS.

const evalPageScripts = () => {
  const scripts = document.querySelectorAll('script');

  scripts.forEach((script: HTMLScriptElement) => {
    const newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.src = script.src;

    if (script.parentNode) {
      script.parentNode.removeChild(script);
    }

    return document.body.appendChild(newScript);
  })
};

export default evalPageScripts;

kvba
quelle
-1

Versuchen Sie die Funktion eval ().

data.newScript = '<script type="text/javascript">//my script...</script>'
var element = document.getElementById('elementToRefresh');
element.innerHTML = data.newScript;
eval(element.firstChild.innerHTML);

Dies ist ein echtes Beispiel aus einem Projekt, das ich entwickle. Danke an diesen Beitrag

IgniteCoders
quelle
-1

Hier ist meine Lösung in einem aktuellen Projekt.

<!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>

Grau
quelle