javascript - Kan inte skapa DocumentFragment som lagrar td, tr eller th?


Är det möjligt att låta DocumentFragments innehålla tr-, th- eller td-taggar?

Om jag gör detta:

var template = document.createRange().createContextualFragment(
        '<table></table>'
    );

    console.log(template.childNodes);

Jag får utdata av [table].

Om jag gör detta:

var template = document.createRange().createContextualFragment(
        '<td></td>'
    );

    console.log(template.childNodes);

Jag får utdata av []!!!?!?

Om jag gör detta:

var template = document.createRange().createContextualFragment(
        '<td><p></p></td>'
    );

    console.log(template.childNodes);

Jag får [p]??!?!?!??!?!??!

Och slutligen, om jag gör detta:

var template = document.createRange().createContextualFragment(
        '<span><td></td></span>'
    );

    console.log(template.childNodes);

Jag får [span] - var tog td vägen??!

Jag förstår inte inkonsekvensen här. Är det möjligt för dokumentfragment att bara innehålla vissa element? Det jag skulle vilja göra är att göra något liknande det andra här ovan, och sedan hämta td med querySelector.

Tack

Svar #1

Lösning 1

Använd createDocumentFragment(), skapa ett <td>-element och lägg till det i DocumentFragment med appendChild():

var frag = document.createDocumentFragment()
frag.appendChild( document.createElement( 'td' ) )
console.log( frag.childNodes )  // output => [td]

Lösning 2

Skapa ett <template>-element, lägg till HTML-innehåll i innerHTML, och hämta sedan DocumentFragment från content-egenskapen:

var template = document.createElement( 'template' )
template.innerHTML = '<td></td>'
var frag = template.content
console.log( frag.childNodes )   // output => [td]

Svar #2

Jag har skrivit ett bibliotek för att göra just detta (skapa dokumentfragment från en HTML-sträng). Det kallas html-fragment.

Detta lilla bibliotek försöker använda range-API:et (som du gör), men om noden på översta nivån är en nod som behöver en specifik föräldranod (som en td), kommer det att försöka några andra lösningar, till exempel en template om den stöds, annars gör det det på det "gammaldags sättet" där det först omsluter med rätt föräldratagg och sedan lägger till de noder du ville ha i dokumentfragmentet (utan de tillfälliga föräldranoderna).

Du skulle använda det så här:

var html = '<td><p>Hello World</p></td>';
var fragment = HtmlFragment(html);

console.log(fragment.firstChild) //td
<script src="https://unpkg.com/[email /lib/html-fragment.min.js"></script>