Traté de cargar algunos scripts en una página usando innerHTML
un <div>
. Parece que el script se carga en el DOM, pero nunca se ejecuta (al menos en Firefox y Chrome). ¿Hay alguna forma de ejecutar scripts al insertarlos innerHTML
?
Código de muestra:
<!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>
fuente
<script>
etiquetainnerHTML
puede ser corto, pero no funciona. Todo es solo texto plano hasta que se ejecutaeval()
. Y lamentablemente,eval()
no analiza las etiquetas HTML, por lo que terminas con una cadena de problemas.Aquí hay una solución muy interesante para su problema: http://24ways.org/2005/have-your-dom-and-script-it-too
Entonces use esto en lugar de las etiquetas de script:
<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />
fuente
onload
atributo. Además, esto requiere que exista un archivo adicional y que se cargue. La solución de momo es un compromiso menor.<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
(esto no hará una solicitud de red) En realidad ... NO necesita una imagen, hacer referencia a una imagen no existente y en lugar deonload
usaronerror
(pero esto hará una solicitud de red)Aquí hay un método que reemplaza recursivamente todos los scripts por ejecutables:
Llamada de ejemplo:
fuente
Puede crear un script y luego inyectar el contenido.
Esto funciona en todos los navegadores :)
fuente
document.documentElement
lugar.<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>
elementos. Por ejemplo<img onerror="..." src="#">
y<body onload="...">
. Si desea ser técnico, esto no funcionará en documentos que no sean HTML / SVG debido al espacio de nombres no explícito.Usé este código, está funcionando bien
fuente
Tuve este problema con innerHTML, tuve que agregar un script Hotjar a la etiqueta "head" de mi aplicación Reactjs y tendría que ejecutarse justo después de agregarlo.
Una de las buenas soluciones para la importación dinámica de nodos en la etiqueta "head" es el módulo React-helment .
Además, hay una solución útil para el problema propuesto:
¡No hay etiquetas de script en innerHTML!
Resulta que HTML5 no permite que las etiquetas de script se agreguen dinámicamente usando la propiedad innerHTML. Por lo tanto, lo siguiente no se ejecutará y no habrá ninguna alerta que diga ¡Hola mundo!
Esto está documentado en la especificación HTML5:
Pero cuidado, esto no significa que innerHTML esté a salvo de secuencias de comandos entre sitios. Es posible ejecutar JavaScript a través de innerHTML sin usar etiquetas como se ilustra en la página innerHTML de MDN .
Solución: agregar scripts dinámicamente
Para agregar dinámicamente una etiqueta de secuencia de comandos, debe crear un nuevo elemento de secuencia de comandos y agregarlo al elemento de destino.
Puede hacer esto para scripts externos:
Y guiones en línea:
fuente
Para cualquiera que todavía intente hacer esto, no, no puede inyectar un script usando
innerHTML
, pero es posible cargar una cadena en una etiqueta de script usando unBlob
yURL.createObjectURL
.He creado un ejemplo que le permite ejecutar una cadena como secuencia de comandos y obtener las 'exportaciones' de la secuencia de comandos a través de una promesa:
He simplificado esto desde mi implementación real, por lo que no prometo que no haya errores. Pero el principio funciona.
Si no le importa recuperar ningún valor después de que se ejecute el script, es aún más fácil; acaba de dejar de lado las
Promise
y losonload
bits. Ni siquiera necesita envolver el script o crear lawindow.__load_script_exports_
propiedad global .fuente
Aquí hay una función recursiva para establecer el innerHTML de un elemento que uso en nuestro servidor de anuncios:
Puedes ver la demo aquí .
fuente
Podrías hacerlo así:
fuente
Aquí una solución que no utiliza
eval
, y funciona con scripts , scripts vinculados , así como con módulos .La función acepta 3 parámetros:
fuente
eval('console.log(this)')
y verá la más obviaeval('let b=100')
... y luego intente accederb
desde fuera de la evaluación ... buena suerte con eso, lo va a necesitarKrasimir Tsonev tiene una gran solución que supera todos los problemas. Su método no necesita usar eval, por lo que no existen problemas de rendimiento ni seguridad. Le permite configurar la cadena innerHTML que contiene html con js y traducirla inmediatamente a un elemento DOM mientras también ejecuta las partes js que existen a lo largo del código. corto, simple y funciona exactamente como quieras.
Disfruta su solución:
http://krasimirtsonev.com/blog/article/Convert-HTML-string-to-DOM-element
Notas importantes:
fuente
Usar en
$(parent).html(code)
lugar deparent.innerHTML = code
.Lo siguiente también corrige los scripts que usan
document.write
y los scripts cargados a través desrc
atributos. Desafortunadamente, incluso esto no funciona con los scripts de Google AdSense.Fuente
fuente
Intente usar template y document.importNode. Aquí hay un ejemplo:
fuente
También puede envolverlo
<script>
así y se ejecutará:Tenga en cuenta: el alcance interno se
srcdoc
refiere al iframe, por lo que debe usartop
como en el ejemplo anterior para acceder al documento principal.fuente
Sí, puede hacerlo, pero debe hacerlo fuera del DOM y el orden debe ser correcto.
... alertará a 'foo'. Esto no funcionará:
E incluso esto no funcionará, porque el nodo se inserta primero:
fuente
Mi solución para este problema es configurar un Observador de mutaciones para detectar
<script></script>
nodos y luego reemplazarlo por un nuevo<script></script>
nodo con el mismo src. Por ejemplo:fuente
La mención de Gabriel Garcia de MutationObservers está en el camino correcto, pero no funcionó para mí. No estoy seguro de si fue por una peculiaridad del navegador o por un error de mi parte, pero la versión que terminó funcionando para mí fue la siguiente:
Por supuesto, debe reemplazarlo
element_to_watch
con el nombre del elemento que se está modificando.node.parentElement.added
se usa para almacenar las etiquetas de script que se agregan adocument.head
. En la función utilizada para cargar la página externa, puede usar algo como lo siguiente para eliminar las etiquetas de script que ya no son relevantes:Y un ejemplo del comienzo de una función de carga:
fuente
MutationObserver
cada vez que se agrega un elemento al documento, ¿verdad? Por cierto, me pregunto por qué dices que mi código no es funcional.Para mí, la mejor manera es insertar el nuevo contenido HTML a través de innerHtml y luego usar
El setTimeout no es obligatorio pero funciona mejor. Esto funcionó para mí.
fuente
Ejecutar (Java Script) etiqueta de innerHTML
Reemplace su elemento de script con div que tenga un atributo de clase class = "javascript" y ciérrelo con
</div>
No cambie el contenido que desea ejecutar (anteriormente estaba en la etiqueta del script y ahora está en la etiqueta div)
Agregue un estilo en su página ...
<style type="text/css"> .javascript { display: none; } </style>
Ahora ejecute eval usando jquery (Jquery js ya debería estar incluido)
Puedes explorar más aquí , en mi blog.
fuente