4

是否可以让 DocumentFragments 包含 tr、th 或 td 标签?

如果我这样做:

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

    console.log(template.childNodes);

我得到[table].

如果我这样做:

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

    console.log(template.childNodes);

我得到了[]!!!?!?的输出

如果我这样做:

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

    console.log(template.childNodes);

我得到[p]了??!?!?!??!?!??!

最后,如果我这样做:

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

    console.log(template.childNodes);

我明白[span]了 - td 去哪儿了??!

我不明白这里的不一致。文档片段是否可能只包含某些元素?我想做的是做类似于上面第二个的事情,然后使用querySelector.

谢谢

4

3 回答 3

5

解决方案 1

使用createDocumentFragment(),创建一个<td>元素,并将其添加到 DocumentFragment 中appendChild()

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

解决方案 2

创建一个<template>元素,将 HTML 内容添加到innerHTML,然后从content属性中获取 DocumentFragment:

var template = document.createElement( 'template' )
template.innerHTML = '<td></td>'
var frag = template.content
console.log( frag.childNodes )   // output => [td]
于 2017-03-30T08:47:51.430 回答
1

我为此编写了一个库(从 HTML 字符串创建文档片段)。它被称为html-fragment

这个小库尝试使用范围 API(就像您正在做的那样),但是如果顶级节点是需要特定父节点的节点(例如 a td),它将尝试尝试一些其他解决方案,例如templateif它是受支持的,否则它会以“老式方式”执行它,首先用正确的父标签包装它,然后将您想要的节点添加到文档片段(没有临时父节点)。

你会像这样使用它:

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>

于 2017-05-22T02:22:21.117 回答
-1
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)
}
于 2020-09-11T06:03:02.933 回答