简体   繁体   English

无法创建 DocumentFragment 存储 td、tr 或 th?

[英]Cannot create DocumentFragment storing td, tr or th?

Is it possible to have DocumentFragments contain tr, th or td tags?是否可以让 DocumentFragments 包含 tr、th 或 td 标签?

If I do this:如果我这样做:

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

    console.log(template.childNodes);

I get the output of [table] .我得到[table]的输出。

If I do this:如果我这样做:

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

    console.log(template.childNodes);

I get the output of [] !!!?!?我得到[]的输出!!!?!?

If I do this:如果我这样做:

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

    console.log(template.childNodes);

I get [p] ??!?!?!??!?!??!我得到[p] ??!?!?!??!?!??!

And finally if I do this:最后,如果我这样做:

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

    console.log(template.childNodes);

I get [span] - where's the td gone??!我明白了[span] - td 去哪儿了??!

I don't understand the inconsistency here.我不明白这里的不一致。 Is it possible for document fragments to only hold certain elements?文档片段是否可能只包含某些元素? What I would like to do is do something akin to the second this above, and then retrieve the td using querySelector .我想做的是做一些类似于上面第二个的事情,然后使用querySelector检索 td 。

Thanks谢谢

Solution 1解决方案1

Use createDocumentFragment() , create a <td> element, and add it to the DocumentFragment with appendChild() :使用createDocumentFragment() ,创建一个<td>元素,并使用appendChild()将其添加到 DocumentFragment 中:

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

Solution 2解决方案2

Create a <template> element, add HTML content to innerHTML , then get the DocumentFragment from the content property:创建一个<template>元素,将 HTML 内容添加到innerHTML ,然后从content属性中获取 DocumentFragment :

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

I have written a library for doing just this (creating document fragments from an HTML string).我为此编写了一个库(从 HTML 字符串创建文档片段)。 It is called html-fragment .它被称为html-fragment

This small library attempts to use the range API (as you are doing), but if the top level node is a node that needs a specific parent node (such as a td ), it will attempt to try some other solutions, such as a template if it is supported, otherwise it does it the "old fashioned way" where it wraps it first with the correct parent tag, and then adds the nodes you wanted to the document fragment (without the temporary parent nodes).这个小库尝试使用 range API(就像你在做的那样),但是如果顶级节点是一个需要特定父节点的节点(例如td ),它会尝试尝试其他一些解决方案,例如template如果支持),否则它会以“老式方式”执行,首先使用正确的父标签包装它,然后将您想要的节点添加到文档片段(没有临时父节点)。

You would use it like so:你会像这样使用它:

 var html = '<td><p>Hello World</p></td>'; var fragment = HtmlFragment(html); console.log(fragment.firstChild) //td
 <script src="https://unpkg.com/html-fragment@1.1.0/lib/html-fragment.min.js"></script>

const range = new Range()
const tableRange = new Range()

const table = document.createElement('table')
const tbody = document.createElement('tbody')
const tr = document.createElement('tr')
const colgroup = document.createElement('colgroup')

/**
 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Table_content
 */
const tableTags = [
  'tbody',
  'thead',
  'tfoot',
  'caption',
  'colgroup',
  'col',
  'tr',
  'td',
  'th'
]


export function createFragment(str: string) {
  const firstTag = str.match(/^<(([a-z]|-)+)/)?.[1]
  if (firstTag && tableTags.includes(firstTag)) {
    switch (firstTag) {
      case 'tbody':
      case 'thead':
      case 'tfoot':
      case 'caption':
      case 'colgroup':
        tableRange.selectNodeContents(table)
        break
      case 'tr':
        tableRange.selectNodeContents(tbody)
        break
      case 'td':
      case 'th':
        tableRange.selectNodeContents(tr)
        break
      case 'col':
        tableRange.selectNodeContents(colgroup)
        break
      default:
        break
    }
    return tableRange.createContextualFragment(str)
  }
  return range.createContextualFragment(str)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM