createdocumentfragment javascript jquery documentfragment

javascript - createdocumentfragment - Insertar HTML arbitrario en un DocumentFragment



createdocumentfragment js (9)

Sé que la adición de innerHTML a los fragmentos de documentos se ha discutido recientemente y es de esperar que se incluya en el estándar DOM. Pero, ¿cuál es la solución que se supone que debes usar mientras tanto?

Es decir, tomar

var html = ''<div>x</div><span>y</span>''; var frag = document.createDocumentFragment();

Quiero tanto la div como la span dentro del frag , con una sola línea fácil.

Puntos de bonificación por no haber bucles. jQuery está permitido, pero ya he intentado $(html).appendTo(frag) ; frag sigue vacío después.


@PAEz señaló que el enfoque de @ RobW no incluye texto entre elementos. Eso es porque los children solo toman Elementos , y no Nodos . Un enfoque más robusto podría ser el siguiente:

var fragment = document.createDocumentFragment(), intermediateContainer = document.createElement(''div''); intermediateContainer.innerHTML = "Wubba<div>Lubba</div>Dub<span>Dub</span>"; while (intermediateContainer.childNodes.length > 0) { fragment.appendChild(intermediateContainer.childNodes[0]); }

El rendimiento puede sufrir en grandes partes de HTML, sin embargo, es compatible con muchos navegadores antiguos y conciso.


Actualmente, la única forma de rellenar un fragmento de documento utilizando solo una cadena es crear un objeto temporal y recorrer los elementos secundarios para agregarlos al fragmento.

  • Como no se adjunta al documento, no se procesa nada, por lo que no hay un impacto en el rendimiento.
  • Se ve un bucle, pero solo se recorre en bucle a través de los primeros niños. La mayoría de los documentos tienen solo unos pocos elementos semi-raíz, por lo que tampoco es un gran problema.

Si desea crear un documento completo, use el DOMParser en su lugar. Echa un vistazo a esta respuesta .

Código:

var frag = document.createDocumentFragment(), tmp = document.createElement(''body''), child; tmp.innerHTML = ''<div>x</div><span>y</span>''; while (child = tmp.firstElementChild) { frag.appendChild(child); }

Una línea (dos líneas para facilitar la lectura) (entrada: String html , salida: DocumentFragment frag ):

var frag =document.createDocumentFragment(), t=document.createElement(''body''), c; t.innerHTML = html; while(c=t.firstElementChild) frag.appendChild(c);


Aquí hay una forma en los navegadores modernos sin bucles:

var temp = document.createElement(''template''); temp.innerHTML = ''<div>x</div><span>y</span>''; var frag = temp.content;

o, como reutilizable

function fragmentFromString(strHTML) { var temp = document.createElement(''template''); temp.innerHTML = strHTML; return temp.content; }

ACTUALIZACIÓN: Encontré una forma más sencilla de usar la idea principal de Pete, que agrega IE11 a la mezcla:

function fragmentFromString(strHTML) { return document.createRange().createContextualFragment(strHTML); }

La cobertura es mejor que el método <template> y se probó bien en IE11, Ch, FF.

Prueba en vivo / demostración disponible en http://pagedemos.com/str2fragment/


Aquí hay una solución x-browser, probada en IE10, IE11, Edge, Chrome y FF.

function HTML2DocumentFragment(markup: string) { if (markup.toLowerCase().trim().indexOf(''<!doctype'') === 0) { let doc = document.implementation.createHTMLDocument(""); doc.documentElement.innerHTML = markup; return doc; } else if (''content'' in document.createElement(''template'')) { // Template tag exists! let el = document.createElement(''template''); el.innerHTML = markup; return el.content; } else { // Template tag doesn''t exist! var docfrag = document.createDocumentFragment(); let el = document.createElement(''body''); el.innerHTML = markup; for (let i = 0; 0 < el.childNodes.length;) { docfrag.appendChild(el.childNodes[i]); } return docfrag; } }


Como dijo @dandavis, hay una forma estándar utilizando la etiqueta de plantilla.
Pero si desea admitir IE11 y necesita analizar elementos de tabla como ''<td> prueba'', puede usar esta función:

function createFragment(html){ var tmpl = document.createElement(''template''); tmpl.innerHTML = html; if (tmpl.content == void 0){ // ie11 var fragment = document.createDocumentFragment(); var isTableEl = /^[^/S]*?<(t(?:head|body|foot|r|d|h))/i.test(html); tmpl.innerHTML = isTableEl ? ''<table>''+html : html; var els = isTableEl ? tmpl.querySelector(RegExp.$1).parentNode.childNodes : tmpl.childNodes; while(els[0]) fragment.appendChild(els[0]); return fragment; } return tmpl.content; }


Para hacer esto con la menor cantidad de líneas posible, puede envolver su contenido en otra división para que no tenga que hacer un bucle o llamar a apendchild más de una vez. Al usar jQuery (como se mencionó está permitido), puede crear muy rápidamente un nodo de dominio sin conexión y colocarlo en el fragmento.

var html = ''<div id="main"><div>x</div><span>y</span></div>''; var frag = document.createDocumentFragment(); frag.appendChild($​(html)[0]);


Utilice Range.createContextualFragment :

var html = ''<div>x</div><span>y</span>''; var range = document.createRange(); // or whatever context the fragment is to be evaluated in. var parseContext = document.body; range.selectNodeContents(parseContext); var fragment = range.createContextualFragment(html);

Tenga en cuenta que las diferencias principales entre este enfoque y el enfoque <template> son:

  • Range.createContextualFragment es un poco más compatible (IE11 lo acaba de conseguir, Safari, Chrome y FF lo han tenido durante un tiempo).

  • Los elementos personalizados dentro del HTML se actualizarán inmediatamente con el rango, pero solo cuando se clonen en el documento real con la plantilla. El enfoque de la plantilla es un poco más "inerte", lo que puede ser deseable.


createDocumentFragment crea un "contenedor" de DOM vacío. innerHtml y otros métodos funcionan solo en nodos DOM (no en el contenedor), por lo que primero tiene que crear sus nodos y luego agregarlos al fragmento. Puede hacerlo usando un método doloroso de appendChild o puede crear un nodo y modificar el valor de innerHtml y agregarlo a su fragmento.

var frag = document.createDocumentFragment(); var html = ''<div>x</div><span>y</span>''; var holder = document.createElement("div") holder.innerHTML = html frag.appendChild(holder)

con jquery simplemente mantienes y construyes tu html como una cadena. Si desea convertirlo en un objeto jquery para realizar operaciones similares a jquery, simplemente haga $ (html), lo que crea un objeto jquery en la memoria. Una vez que esté listo para agregarlo, simplemente lo agrega a un elemento existente en una página


var html = ''<div>x</div><span>y</span>''; var frag = document.createDocumentFragment(); var e = document.createElement(''i''); frag.appendChild(e); e.insertAdjacentHTML(''afterend'', html); frag.removeChild(e);