Ich habe versucht, einige Skripte mit einem innerHTML
auf eine Seite zu laden <div>
. Es scheint, dass das Skript in das DOM geladen wird, aber es wird nie ausgeführt (zumindest in Firefox und Chrome). Gibt es eine Möglichkeit, Skripte beim Einfügen auszuführen innerHTML
?
Beispielcode:
<!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>
quelle
<script>
Tags mitinnerHTML
möglicherweise kurz ist, aber es funktioniert nicht. Es ist alles nur einfacher Text, bis er durchlaufen wirdeval()
. Und leider werdeneval()
HTML-Tags nicht analysiert, sodass Sie eine Reihe von Problemen haben.Hier ist eine sehr interessante Lösung für Ihr Problem: http://24ways.org/2005/have-your-dom-and-script-it-too
Verwenden Sie dies anstelle von Skript-Tags:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
quelle
onload
Attribut zu schreiben . Dazu muss auch eine zusätzliche Datei vorhanden sein und geladen werden. Die Lösung von momo ist weniger ein Kompromiss.<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
(dies führt keine Netzwerkanforderung aus) codieren. Eigentlich ... benötigen Sie KEIN Image, verweisen auf ein nicht vorhandenes Image undonload
verwenden es nichtonerror
(aber dies führt eine Netzwerkanforderung aus)Hier ist eine Methode, die alle Skripte rekursiv durch ausführbare ersetzt:
Beispielaufruf:
quelle
Sie können ein Skript erstellen und dann den Inhalt einfügen.
Dies funktioniert in allen Browsern :)
quelle
document.documentElement
stattdessen.<script>
var g = document.createElement('script');
var s = document.getElementsByTagName('script')[0]; //reference this script
g.text = "alert(\"hi\");"
s.parentNode.insertBefore(g, s);
</script>
<script>
Elemente ausführen . ZB<img onerror="..." src="#">
und<body onload="...">
. Wenn Sie technisch sein möchten, funktioniert dies aufgrund des unerklärlichen Namespaces auch in Nicht-HTML / SVG-Dokumenten nicht.Ich habe diesen Code verwendet, er funktioniert einwandfrei
quelle
Ich hatte dieses Problem mit innerHTML. Ich musste ein Hotjar-Skript an das "head" -Tag meiner Reactjs-Anwendung anhängen und es musste direkt nach dem Anhängen ausgeführt werden.
Eine der guten Lösungen für den dynamischen Knotenimport in das "head" -Tag ist React-helment Modul.
Es gibt auch eine nützliche Lösung für das vorgeschlagene Problem:
Keine Skript-Tags in innerHTML!
Es stellt sich heraus, dass HTML5 das dynamische Hinzufügen von Skript-Tags mithilfe der innerHTML-Eigenschaft nicht zulässt. Das Folgende wird also nicht ausgeführt und es wird keine Warnung mit der Aufschrift "Hallo Welt!" Angezeigt.
Dies ist in der HTML5-Spezifikation dokumentiert:
Beachten Sie jedoch, dass innerHTML nicht vor Cross-Site-Scripting geschützt ist. Es ist möglich, JavaScript über innerHTML auszuführen, ohne Tags zu verwenden, wie auf der innerHTML-Seite von MDN dargestellt .
Lösung: Dynamisches Hinzufügen von Skripten
Um ein Skript-Tag dynamisch hinzuzufügen, müssen Sie ein neues Skriptelement erstellen und an das Zielelement anhängen.
Sie können dies für externe Skripte tun:
Und Inline-Skripte:
quelle
Für alle, die dies noch versuchen, nein, Sie können ein Skript nicht mit einfügen
innerHTML
, aber es ist möglich, eine Zeichenfolge mit einemBlob
und in ein Skript-Tag zu ladenURL.createObjectURL
.Ich habe ein Beispiel erstellt, mit dem Sie eine Zeichenfolge als Skript ausführen und die 'Exporte' des Skripts durch ein Versprechen zurückgeben können:
Ich habe dies gegenüber meiner eigentlichen Implementierung vereinfacht, daher gibt es keine Versprechungen, dass keine Fehler darin enthalten sind. Aber das Prinzip funktioniert.
Wenn Sie nach der Ausführung des Skripts keinen Wert mehr zurückerhalten möchten, ist dies noch einfacher. Lass einfach die
Promise
undonload
Bits weg . Sie müssen nicht einmal das Skript umbrechen oder die globalewindow.__load_script_exports_
Eigenschaft erstellen .quelle
Hier ist eine rekursive Funktion zum Festlegen der innerHTML eines Elements, das ich in unserem Ad-Server verwende:
Sie können die Demo hier sehen .
quelle
Sie könnten es so machen:
quelle
Hier eine Lösung, die Skripte , verknüpfte Skripte sowie Module nicht verwendet
eval
und mit diesen funktioniert .Die Funktion akzeptiert 3 Parameter:
quelle
eval('console.log(this)')
Sie und Sie werden den offensichtlichsten seheneval('let b=100')
.. und versuchen Sie dann,b
von außerhalb des eval zuzugreifen .... viel Glück damit, Sie werden es brauchenKrasimir Tsonev hat eine großartige Lösung, die alle Probleme überwindet. Seine Methode muss nicht eval verwenden, daher gibt es keine Leistungs- oder Sicherheitsprobleme. Sie können festlegen, dass die innerHTML-Zeichenfolge HTML mit js enthält, und diese sofort in ein DOM-Element übersetzen, während auch die im Code vorhandenen js-Teile ausgeführt werden. kurz, einfach und funktioniert genau so, wie Sie es möchten.
Genießen Sie seine Lösung:
http://krasimirtsonev.com/blog/article/Convert-HTML-string-to-DOM-element
Wichtige Notizen:
quelle
Verwenden Sie
$(parent).html(code)
anstelle vonparent.innerHTML = code
.Im Folgenden werden auch die verwendeten
document.write
Skripte und die über dassrc
Attribut geladenen Skripte behoben . Leider funktioniert auch dies nicht mit Google AdSense-Skripten.Quelle
quelle
Versuchen Sie es mit template und document.importNode. Hier ist ein Beispiel:
quelle
Sie können Ihre auch so verpacken
<script>
und es wird ausgeführt:Bitte beachten Sie: Der Bereich im Inneren
srcdoc
bezieht sich auf den Iframe. Sie müssen ihn alsotop
wie im obigen Beispiel verwenden, um auf das übergeordnete Dokument zuzugreifen.quelle
Ja, das können Sie, aber Sie müssen es außerhalb des DOM tun und die Reihenfolge muss stimmen.
... wird 'foo' alarmieren. Das wird nicht funktionieren:
Und selbst das funktioniert nicht, weil der Knoten zuerst eingefügt wird:
quelle
Meine Lösung für dieses Problem besteht darin, einen Mutationsbeobachter so einzustellen , dass er
<script></script>
Knoten erkennt und ihn dann durch einen neuen<script></script>
Knoten mit demselben src ersetzt. Beispielsweise:quelle
Gabriel Garcias Erwähnung von MutationObservers ist auf dem richtigen Weg, hat aber für mich nicht ganz funktioniert. Ich bin mir nicht sicher, ob dies an einer Browser-Eigenart oder an einem Fehler auf meiner Seite lag, aber die Version, die letztendlich für mich funktioniert hat, war die folgende:
Natürlich sollten Sie ersetzen
element_to_watch
den Namen des Elements , das geändert wird.node.parentElement.added
wird zum Speichern der hinzugefügten Skript-Tags verwendetdocument.head
. In der Funktion zum Laden der externen Seite können Sie Folgendes verwenden, um nicht mehr relevante Skript-Tags zu entfernen:Und ein Beispiel für den Beginn einer Ladefunktion:
quelle
MutationObserver
jedes Mal ein neues hinzufügen, wenn ein Element an das Dokument angehängt wird, oder? Übrigens frage ich mich, warum mein Code nicht funktioniert.Für mich ist der beste Weg, den neuen HTML-Inhalt über innerHtml einzufügen und dann zu verwenden
Das setTimeout ist nicht erforderlich, funktioniert aber besser. Das hat bei mir funktioniert.
quelle
Führen Sie das Tag (Java Script) von innerHTML aus
Ersetzen Sie Ihr Skriptelement durch div mit dem Klassenattribut class = "javascript" und schließen Sie es mit
</div>
Ändern Sie nicht den Inhalt, den Sie ausführen möchten (zuvor befand er sich im Skript-Tag und jetzt im div-Tag).
Fügen Sie Ihrer Seite einen Stil hinzu ...
<style type="text/css"> .javascript { display: none; } </style>
Führen Sie nun eval mit jquery aus (Jquery js sollte bereits enthalten sein)
Weitere Informationen finden Sie hier in meinem Blog.
quelle