Agregar cadena HTML al DOM

121

Cómo agregar esta cadena HTML

var str = '<p>Just some <span>text</span> here</p>';

al DIV con el ID 'test'que está en el DOM?

(Por cierto div.innerHTML += str;no es aceptable).

Šime Vidas
fuente

Respuestas:

243

Úselo insertAdjacentHTMLsi está disponible; de ​​lo contrario, use algún tipo de respaldo. insertAdherentHTML es compatible con todos los navegadores actuales .

div.insertAdjacentHTML( 'beforeend', str );

Demostración en vivo: http://jsfiddle.net/euQ5n/

Neil
fuente
1
@alex Es el mismo concepto: analizar una cadena HTML y colocarla en el DOM. Pero la funcionalidad es diferente: innerHTMLcoloca la cadena en el elemento (reemplazando a todos los hijos), mientras que la insertAdjacentHTMLcoloca (1) antes del elemento, (2) después del elemento, (3) dentro del elemento antes del primer hijo o (4) dentro del elemento después del último hijo.
Šime Vidas
3
@alex insertAdjacentHTMLes más rápido que agregar a innerHTML, porque insertAdjacentHTMLno serializa ni analiza los elementos secundarios existentes del elemento.
hsivonen
2
Además, insertAdjacentHTMLmantiene los valores de los elementos de formulario alterados, mientras que agregar a innerHTMLreconstruye el elemento y pierde todo el contexto del formulario.
Brandon Gano
20

¿Es esto aceptable?

var child = document.createElement('div');
child.innerHTML = str;
child = child.firstChild;
document.getElementById('test').appendChild(child);

jsFiddle .

Sin embargo , la respuesta de Neil es una solución mejor.

alex
fuente
1
@ Šime Trabajar con la API DOM siempre se siente como un truco: P ¿Preferiría anular la serialización de la cadena sin innerHTML ?
alex
Bueno, sí, si hay otra forma de utilizar el analizador HTML del navegador, me encantaría saber ...
Šime Vidas
1
@ Šime - Creo que solo hay dos formas de utilizar el analizador HTML del navegador, innerHTML y document.write. Y si crees que innerHTML es un truco ...
Alohci
@Alohci No es otra manera: insertAdjacentHTML.
Šime Vidas
1
@ Šime -Gracias. Encontré la versión WHATWG. Está en la especificación de análisis y serialización de DOM . Indica que, además de innerHTML e insertAdjectedHTML, hay outerHTML y, creo, createContextualFragment.
Alohci
16

Actuación

AppendChild(E) es más del doble de rápido que otras soluciones en Chrome y Safari, insertAdjacentHTML(F) es más rápido en Firefox. La innerHTML=(B) (no confundir con +=(A)) es la segunda solución rápida en todos los navegadores y es mucho más útil que E y F.

Detalles

Configurar entorno (2019.07.10) MacOs High Sierra 10.13.4 en Chrome 75.0.3770 (64 bits), Safari 11.1.0 (13604.5.6), Firefox 67.0.0 (64 bits)

ingrese la descripción de la imagen aquí

  • en Chrome E (140k operaciones por segundo) es el más rápido, B (47k) y F (46k) son el segundo, A (332) es el más lento
  • en firefox F (94k) es el más rápido, luego B (80k), D (73k), E (64k), C (21k) el más lento es A (466)
  • en Safari E (207k) es el más rápido, luego B (89k), F (88k), D (83k), C (25k), el más lento es A (509)

Puede reproducir la prueba en su máquina aquí

Kamil Kiełczewski
fuente
12

La idea es usar innerHTMLen un elemento intermediario y luego mover todos sus nodos secundarios a donde realmente los desea appendChild.

var target = document.getElementById('test');
var str = '<p>Just some <span>text</span> here</p>';

var temp = document.createElement('div');
temp.innerHTML = str;
while (temp.firstChild) {
  target.appendChild(temp.firstChild);
}

Esto evita eliminar cualquier controlador de eventos, div#testpero aún le permite agregar una cadena de HTML.

Chris Calo
fuente
3

La forma correcta es usar insertAdjacentHTML. En Firefox anterior a la 8, puede volver a usarlo Range.createContextualFragmentsi strno contiene scriptetiquetas.

Si strcontiene scriptetiquetas, debe eliminar scriptelementos del fragmento devuelto por createContextualFragmentantes de insertar el fragmento. De lo contrario, se ejecutarán los scripts. ( insertAdjacentHTMLmarca los scripts como no ejecutables).

hsivonen
fuente
Gracias por mencionar createContextualFragment . Estaba buscando una manera de hacer que algunas inclusiones html con scripts se ejecuten solo si el usuario acepta configurar una cookie.
schliflo
3

Hack rápido :


<script>
document.children[0].innerHTML="<h1>QUICK_HACK</h1>";
</script>

Casos de uso :

1: Guarde como archivo .html y ejecútelo en Chrome o Firefox o Edge. (IE no funcionará)

2: usar en http://js.do

En acción: http://js.do/HeavyMetalCookies/quick_hack

Desglosado con comentarios:

<script>

//: The message "QUICK_HACK" 
//: wrapped in a header #1 tag.
var text = "<h1>QUICK_HACK</h1>";

//: It's a quick hack, so I don't
//: care where it goes on the document,
//: just as long as I can see it.
//: Since I am doing this quick hack in
//: an empty file or scratchpad, 
//: it should be visible.
var child = document.children[0];

//: Set the html content of your child
//: to the message you want to see on screen.
child.innerHTML = text;

</script>

Razón por la que publiqué:

JS.do tiene dos elementos imprescindibles:

  1. Sin autocompletar
  2. Compatible con monitores verticales

Pero no muestra mensajes de console.log. Vine aquí buscando una solución rápida. Solo quiero ver los resultados de algunas líneas de código del bloc de notas, las otras soluciones son demasiado trabajo.

JMI MADISON
fuente
1

¿Por qué eso no es aceptable?

document.getElementById('test').innerHTML += str

sería la forma de libro de texto de hacerlo.

Nick Brunt
fuente
4
Sin embargo, mataría a los controladores de eventos adjuntos #test. Eso generalmente no es deseable.
alex
Interesante que haga eso. Realmente no parece lógico.
Nick Brunt
2
Es lógico, supongo, si piensa en la serialización del HTML en una cadena y luego volver a configurar el HTML.
alex
Supongo que el JavaScript tendría que ejecutarse nuevamente para restablecer el controlador de eventos. Lo suficientemente justo.
Nick Brunt
1
@Nick No desea secuenciar (serializar) una parte del DOM solo para poder concatenarlo con otra cadena y luego analizar todo de nuevo en el DOM. Como dijo Alex, la serialización no registrará los controladores de eventos enlazados (entre otras cosas). Incluso si la serialización pudiera capturar todo, no querría hacerlo.
Šime Vidas
0

Esto puede resolver

 document.getElementById("list-input-email").insertAdjacentHTML('beforeend', '<div class=""><input type="text" name="" value="" class="" /></div>');
Rafael Senne
fuente
3
Bienvenido a Stack overflow. Explique su código como parte de una respuesta para proporcionar algo de contexto en lugar de simplemente pegar una sola línea de código. Aunque lo entienda, es posible que otros no entiendan lo que está haciendo.
loan.burger
0

InnerHTML borra todos los datos como eventos para los nodos existentes

append child con firstChild agrega solo el primer niño a innerHTML. Por ejemplo, si tenemos que agregar:

 <p>text1</p><p>text2</p>

solo aparecerá el texto1

¿Qué pasa con esto?

agrega una etiqueta especial a innerHTML agregando child y luego edita externalHTML eliminando la etiqueta que hemos creado. No sé qué tan inteligente es, pero funciona para mí o puede cambiar outerHTML a innerHTML para que no tenga que usar la función reemplazar

function append(element, str)
{

  var child = document.createElement('someshittyuniquetag');
		
  child.innerHTML = str;

  element.appendChild(child);

  child.outerHTML = child.outerHTML.replace(/<\/?someshittyuniquetag>/, '');

// or Even child.outerHTML = child.innerHTML


  
}
<div id="testit">
This text is inside the div
<button onclick="append(document.getElementById('testit'), '<button>dadasasdas</button>')">To div</button>
<button onclick="append(this, 'some text')">to this</button>
</div>

Łukasz Szpak
fuente
0

Más corto : 18 caracteres (no confundir +=(mencionado por OP) con =más detalles aquí )

test.innerHTML=str

Kamil Kiełczewski
fuente