Insertar elementos HTML con JavaScript

105

En lugar de buscar tediosamente soluciones alternativas para cada tipo de atributo y evento cuando se usa la siguiente sintaxis:

elem = document.createElement("div");
elem.id = 'myID';
elem.innerHTML = ' my Text '
document.body.insertBefore(elem,document.body.childNodes[0]);

¿Hay alguna manera en la que pueda declarar todo el elemento HTML como una cadena? me gusta:

elem = document.createElement("<div id='myID'> my Text </div>");
document.body.insertBefore(elem,document.body.childNodes[0]);
El flash
fuente

Respuestas:

124

En lugar de jugar directamente con innerHTMLél, podría ser mejor crear un fragmento y luego insertarlo:

function create(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

var fragment = create('<div>Hello!</div><p>...</p>');
// You can use native DOM methods to insert the fragment:
document.body.insertBefore(fragment, document.body.childNodes[0]);

Beneficios:

  1. Puede usar métodos DOM nativos para la inserción, como insertBefore, appendChild, etc.
  2. Tiene acceso a los nodos DOM reales antes de que se inserten; puede acceder al objeto childNodes del fragmento.
  3. El uso de fragmentos de documentos es muy rápido; más rápido que crear elementos fuera del DOM y en determinadas situaciones más rápido que innerHTML.

Aunque innerHTMLse usa dentro de la función, todo sucede fuera del DOM, por lo que es mucho más rápido de lo que piensas ...

James
fuente
3
Apuesto a que este createDocumentFragment () no sería tan bueno como el innerHTML "heredado".
TheFlash
2
Este método funciona en todos los navegadores modernos. Para IE 5.5 y versiones anteriores, puede realizar una comprobación como :: if (document.createDocumentFragment) {create ('...'); } else {/ * Use innerHTML quizás * /}
James
32
crescentfresh, ayudo en SO porque disfruto ayudando a la gente; Lo siento si una solución no es 100% operativa en todas las situaciones. Si está tan preocupado, ¿por qué no ofrecer su propia solución en lugar de criticar innecesariamente las respuestas ya ofrecidas? ¡Con cualquier abstracción siempre habrá casos extremos! Este es un entorno de aprendizaje; no estamos aquí para darles a las personas una solución en un plato, ¡estamos aquí para ayudarnos mutuamente a mejorar en lo que hacemos! Y lo siento, pero ¿dónde alguien mencionó "AJAX"?
James
1
Lo suficientemente justo. Mis disculpas. Siento que hay tantas abstracciones aquí sin advertencias mencionadas.
Crescent Fresh
1
esto es mucho más complejo de lo que debería ser - la respuesta de sime vidas es mucho mejor
JonnyRaa
83

Tu quieres esto

document.body.insertAdjacentHTML( 'afterbegin', '<div id="myID">...</div>' );
Šime Vidas
fuente
13
No estoy seguro de por qué esta no es la respuesta aceptada. Esto es mucho más simple y obviamente correcto
JonnyRaa
@JonnyLeeds esto no parece funcionar en el bodyelemento, pero funciona bien en cualquier otro elemento.
Phill
1
@Phill Por supuesto que funciona <body>. De hecho, ejecutarlo <body>es mi método estándar para inyectar cosas como hojas de estilo en páginas web a través de la consola. ¿Qué problema tienes?
Šime Vidas
@ ŠimeVidas probablemente porque el elemento del cuerpo no se definió en el momento de la ejecución ... emparejé su línea con window.onload = function () {…} para evitar ese problema
GDY
@Grandy Phill escribió que funciona en otros elementos. Si <body>no estuviera definido, también lo serían todos los demás elementos, por lo que probablemente este no sea un problema de Phill.
Šime Vidas
32

Eche un vistazo a insertAdjectedHTML

var element = document.getElementById("one");
var newElement = '<div id="two">two</div>'
element.insertAdjacentHTML( 'afterend', newElement )
// new DOM structure: <div id="one">one</div><div id="two">two</div>

position es la posición relativa al elemento al que está insertando adyacente:

'beforebegin' Antes del elemento en sí

'afterbegin' Justo dentro del elemento, antes de su primer hijo

'beforeend' Justo dentro del elemento, después de su último hijo

'afterend' Después del propio elemento

svnm
fuente
17

En JavaScript de la vieja escuela, podría hacer esto:

document.body.innerHTML = '<p id="foo">Some HTML</p>' + document.body.innerHTML;

En respuesta a tu comentario:

[...] Estaba interesado en declarar el origen de los atributos y eventos de un nuevo elemento, no el innerHTMLde un elemento.

Sin embargo, debe inyectar el nuevo HTML en el DOM; por eso innerHTMLse usa en el ejemplo de JavaScript de la vieja escuela. El innerHTMLdel BODYelemento se antepone con el nuevo HTML. Realmente no estamos tocando el HTML existente dentro de BODY.

Volveré a escribir el ejemplo mencionado anteriormente para aclarar esto:

var newElement = '<p id="foo">This is some dynamically added HTML. Yay!</p>';
var bodyElement = document.body;
bodyElement.innerHTML = newElement + bodyElement.innerHTML;
// note that += cannot be used here; this would result in 'NaN'

El uso de un marco de JavaScript haría que este código fuera mucho menos detallado y mejoraría la legibilidad. Por ejemplo, jQuery le permite hacer lo siguiente:

$('body').prepend('<p id="foo">Some HTML</p>');
Mathias Bynens
fuente
Bastante bueno. Pero estaba interesado en declarar la fuente de los atributos y eventos de un nuevo elemento, no el HTML interno de un elemento.
TheFlash
1
document.getElementsByTagName('body')[0]de hecho puede ser reemplazado por document.body, buen punto. Sin embargo, si desea anteponer o agregar el nuevo HTML a otro elemento existente en lugar del BODY, tendrá que usar document.getElementById()y / o document.getElementsByTagName(); por eso lo usé en el ejemplo.
Mathias Bynens
1
Además, su código puede volverse muy complicado muy rápidamente si está agregando / insertando directamente "innerHTML"
James
1
@JimmyP: ¡Qué tontería! El propósito mismo de esta pregunta es poder insertar HTML directamente como cadenas en lugar de jugar con funciones para construirlo, atributo por atributo, nodo por nodo, elemento por elemento.
TheFlash
1
esto separa todos los controladores de eventos y puede causar pérdidas de memoria a gran escala.
adardesign
1

Que yo sepa, que, para ser justos, es bastante nuevo y limitado, el único problema potencial con esta técnica es el hecho de que no puede crear dinámicamente algunos elementos de la tabla.

Utilizo un formulario para crear plantillas agregando elementos de "plantilla" a un DIV oculto y luego uso cloneNode (verdadero) para crear un clon y agregarlo según sea necesario. Tenga en cuenta que debe asegurarse de reasignar las identificaciones según sea necesario para evitar la duplicación.

Rpc
fuente
-1

Como otros dijeron , se puede emular la conveniente funcionalidad de prefijo de jQuery :

var html = '<div>Hello prepended</div>';
document.body.innerHTML = html + document.body.innerHTML;

Si bien algunos dicen que es mejor no "meterse" con innerHTML , es confiable en muchos casos de uso, si sabe esto:

Si una <div>, <span>o <noembed>nodo tiene un nodo hijo de texto que incluye los caracteres ( &), ( <) o ( >), innerHTML devuelve estos caracteres como &amp, &lty &gtrespectivamente. Úselo Node.textContentpara obtener una copia correcta del contenido de estos nodos de texto.

https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

O:

var html = '<div>Hello prepended</div>';
document.body.insertAdjacentHTML('afterbegin', html)

insertAdjacentHTMLes probablemente una buena alternativa: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjectedHTML

taseenb
fuente
-2

Si desea insertar código HTML dentro de la etiqueta de la página existente, use Jnerator . Esta herramienta fue creada especialmente para este objetivo.

En lugar de escribir el siguiente código

    var htmlCode = '<ul class=\'menu-countries\'><li
        class=\'item\'><img src=\'au.png\'></img><span>Australia </span></li><li
        class=\'item\'><img src=\'br.png\'> </img><span>Brazil</span></li><li
        class=\'item\'> <img src=\'ca.png\'></img><span>Canada</span></li></ul>';
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;

Puedes escribir una estructura más comprensible

    var jtag = $j.ul({
        class: 'menu-countries',
        child: [
            $j.li({ class: 'item', child: [
                $j.img({ src: 'au.png' }),
                $j.span({ child: 'Australia' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'br.png' }),
                $j.span({ child: 'Brazil' })
            ]}),
            $j.li({ class: 'item', child: [
                $j.img({ src: 'ca.png' }),
                $j.span({ child: 'Canada' })
            ]})
        ]
    });
    var htmlCode = jtag.html();
    var element = document.getElementById('myTag');
    element.innerHTML = htmlCode;
Berezh
fuente