将任意HTML插入DocumentFragment

Dom*_*nic 52 javascript jquery documentfragment

我知道最近已经讨论过添加innerHTML到文档片段,并且希望能够将其包含在DOM标准中.但是,在此期间您应该使用的解决方法是什么?

就是这样

var html = '<div>x</div><span>y</span>';
var frag = document.createDocumentFragment();
Run Code Online (Sandbox Code Playgroud)

我想要divspan内部和内部frag都有一个简单的单行.

没有循环的奖励积分.jQuery是允许的,但我已经尝试过$(html).appendTo(frag); frag之后仍然是空的.

dan*_*vis 86

这是现代浏览器中没有循环的方法:

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

var frag = temp.content;
Run Code Online (Sandbox Code Playgroud)

或者,作为可重复使用的

function fragmentFromString(strHTML) {
    var temp = document.createElement('template');
    temp.innerHTML = strHTML;
    return temp.content;
}
Run Code Online (Sandbox Code Playgroud)

更新:我找到了一种更简单的方法来使用Pete的主要想法,它将IE11添加到组合中:

function fragmentFromString(strHTML) {
    return document.createRange().createContextualFragment(strHTML);
}
Run Code Online (Sandbox Code Playgroud)

覆盖率优于<template>方法,并在IE11,Ch,FF中测试正常.

现场测试/演示http://pagedemos.com/str2fragment/

  • IE根本不支持,所以"现代浏览器"有点误导. (4认同)
  • createContextualFragment的一个问题是,像'<td> test </ td>'这样的html会忽略td(并且只创建'test'文本节点).模板标签解决方案是要走的路.BTW Edge 13现在支持模板标签. (3认同)

Rob*_*b W 24

目前,仅使用字符串填充文档片段的唯一方法是创建临时对象,并遍历子项以将它们附加到片段.

  • 由于它没有附加到文档中,因此不会呈现任何内容,因此不会影响性能.
  • 你看到一个循环,但它只是循环通过第一个孩子.大多数文档只有几个半根元素,所以这也不是什么大问题.

如果要创建整个文档,请改用DOMParser.看看这个答案.

码:

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

单行(两行可读性)(输入:String html,输出:) DocumentFragment frag:

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


Pet*_*ois 12

使用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);
Run Code Online (Sandbox Code Playgroud)

请注意,此方法与<template>方法之间的主要区别是:

  • Range.createContextualFragment得到了更广泛的支持(IE11刚刚获得它,Safari,Chrome和FF已经有一段时间了).

  • HTML中的自定义元素将立即使用范围进行升级,但仅在使用模板克隆到真实文档中时才会升级.模板方法更加"惰性",这可能是理想的.


Mat*_*att 5

@PAEz指出@ RobW的方法不包括元素之间的文本.那是因为children只抓取元素而不是节点.更强大的方法可能如下:

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]);
}
Run Code Online (Sandbox Code Playgroud)

性能可能会受到较大的HTML块的影响,但是,它与许多旧版浏览器兼容并且简洁.

  • 甚至是conciser:`.firstirstChild` - `while(intermediateContainer.firstChild)fragement.appendChild(intermediateContainer.firstChild);` (4认同)

Pat*_*ark 5

从来没有人提供过要求的“简单的单线”。

鉴于变量...

var html = '<div>x</div><span>y</span>';
var frag = document.createDocumentFragment();
Run Code Online (Sandbox Code Playgroud)

……下面这行代码可以解决问题(在 Firefox 67.0.4 中):

frag.append(...new DOMParser().parseFromString(html, "text/html").body.childNodes);
Run Code Online (Sandbox Code Playgroud)