Inserimento di HTML arbitrario in un DocumentFragment

So che l’ aggiunta di innerHTML per documentare i frammenti è stata discussa di recente e speriamo di vedere l’inclusione nello standard DOM. Ma qual è la soluzione che dovresti usare nel frattempo?

Cioè, prendi

 var html = '
x
y'; var frag = document.createDocumentFragment();

Voglio sia il div che lo span all’interno di frag , con un one-liner facile.

Punti bonus per no loop. jQuery è permesso, ma ho già provato $(html).appendTo(frag) ; frag è ancora vuoto in seguito.

    Ecco un modo nei browser moderni senza fare il ciclo:

     var temp = document.createElement('template'); temp.innerHTML = '
    x
    y'; var frag = temp.content;

    o, come riutilizzabile

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

    AGGIORNAMENTO: Ho trovato un modo più semplice per usare l’idea principale di Pete, che aggiunge IE11 al mix:

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

    La copertura è migliore del metodo e testata ok in IE11, Ch, FF.

    Test / demo dal vivo disponibili http://pagedemos.com/str2fragment/

    Attualmente, l’unico modo per riempire un frammento di documento usando solo una stringa è creare un object temporaneo e fare un ciclo attraverso i bambini per aggiungerli al frammento.

    • Dal momento che non è aggiunto al documento, non viene eseguito il rendering, quindi non si verifica alcun impatto sulle prestazioni.
    • Si vede un ciclo, ma è solo in loop attraverso i primi figli. La maggior parte dei documenti ha solo pochi elementi semi-root, quindi non è un grosso problema.

    Se si desidera creare un intero documento, utilizzare invece DOMParser. Dai un’occhiata a questa risposta .

    Codice:

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

    Un one-liner (due righe per la leggibilità) (input: String html , output: DocumentFragment frag ):

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

    Usa Range.createContextualFragment :

     var html = '
    x
    y'; 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);

    Nota che le principali differenze tra questo approccio e l’approccio sono:

    • Range.createContextualFragment è un po ‘più ampiamente supportato (solo per IE11, Safari, Chrome e FF ne hanno avuto per un po’).

    • Gli elementi personalizzati all’interno dell’HTML verranno immediatamente aggiornati con l’intervallo, ma solo quando saranno clonati nel vero documento con il modello. L’approccio al template è un po ‘più “inerte”, che può essere desiderabile.

    @PAEz ha sottolineato che l’approccio di @ RobW non include il testo tra gli elementi. Questo perché i children afferrano solo gli elementi e non i nodes . Un approccio più robusto potrebbe essere il seguente:

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

    Le prestazioni potrebbero risentire di blocchi di HTML più grandi, tuttavia è compatibile con molti browser meno recenti e conciso.

    createDocumentFragment crea un “contenitore” DOM ​​vuoto. innerHtml e altri metodi funzionano solo sui nodes DOM (non sul contenitore), quindi devi prima creare i tuoi nodes e poi aggiungerli al frammento. Puoi farlo usando un doloroso metodo di appendChild oppure puoi creare un nodo e modificarlo innerHtml e aggiungerlo al tuo frammento.

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

    con jquery mantieni e costruisci il tuo html come stringa. Se vuoi convertirlo in un object jquery per eseguire operazioni jQuery su di esso semplicemente fai $ (html) che crea un object jquery in memoria. Una volta che sei pronto ad aggiungerlo, devi semplicemente aggiungerlo a un elemento esistente in una pagina

    Ecco una soluzione x-browser, testata su IE10, IE11, Edge, Chrome e FF.

      function HTML2DocumentFragment(markup: string) { if (markup.toLowerCase().trim().indexOf(' 

    Per fare ciò con il minor numero ansible di righe, puoi avvolgere il contenuto sopra in un altro div in modo da non dover ripetere o chiamare appendchild più di una volta. Usando jQuery (come accennato è permesso) puoi creare rapidamente un nodo dom non assegnato e posizionarlo nel frammento.

     var html = '
    x
    y
    '; var frag = document.createDocumentFragment(); frag.appendChild($​(html)[0]);
     var html = '
    x
    y'; var frag = document.createDocumentFragment(); var e = document.createElement('i'); frag.appendChild(e); e.insertAdjacentHTML('afterend', html); frag.removeChild(e);

    Come ha detto @dandavis, c’è un modo standard usando il tag-modello.
    Ma se ti piace supportare IE11 e devi analizzare gli elementi della tabella come ‘

    test’, puoi usare questa funzione:

     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 ? ''+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; }