将任意HTML插入到DocumentFragment中

我知道在文档片段中添加innerHTML最近已经被讨论过了,希望能够看到DOM标准。 但是,在此期间您应该使用什么解决方法?

那就是拿

 var html = '<div>x</div><span>y</span>'; var frag = document.createDocumentFragment(); 

我想要div和里面的fragspan很简单。

奖励点为没有循环。 jQuery是允许的,但我已经试过$(html).appendTo(frag) ; frag还是空的。

这是现代浏览器没有循环的一种方式:

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

或者,作为可重用的

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

更新:我发现一个更简单的方式来使用皮特的主要想法,它增加了IE11的混合:

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

在IE11中,覆盖率比<template>方法好,并且testing结果正确。

现场testing/演示可用http://pagedemos.com/str2fragment/

目前,仅使用string填充文档片段的唯一方法是创build一个临时对象,并通过子节点循环来将它们附加到片段。

  • 由于它没有附加到文档中,因此没有渲染,因此没有性能影响。
  • 你看到一个循环,但它只是循环通过第一个孩子。 大多数文件只有一些半根元素,所以这也不算什么大事。

如果要创build整个文档,请改用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); } 

一行(可读性为两行)(input: String html ,输出: DocumentFragment frag ):

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

使用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); 

请注意,这种方法和<template>方法之间的主要区别是:

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

  • HTML中的自定义元素将随范围立即升级,但只有在使用模板克隆到真实文档时才会升级。 模板方法有点“惰性”,这可能是可取的。

@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]); } 

性能可能会受到更大的HTML块,然而,它是与许多旧的浏览器兼容,并简洁。

createDocumentFragment创build一个空的DOM“容器”。 innerHtml和其他方法只适用于DOM节点(不是容器),所以你必须先创build你的节点,然后将它们添加到片段。 你可以使用appendChild的一个痛苦的方法来做到这一点,或者你可以创build一个节点并修改它的innerHtml并将其添加到你的片段。

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

与jQuery的你只需保持和build立你的HTML作为一个string。 如果你想将它转换成jquery对象来执行jquery类似的操作,只需要$(html)在内存中创build一个jquery对象。 一旦准备好追加它,只需将其追加到页面上的现有元素即可

这是一个X浏览器解决scheme,在IE10,IE11,Edge,Chrome和FF上testing。

  function HTML2DocumentFragment(markup: string) { if (markup.toLowerCase().trim().indexOf('<!doctype') === 0) { let doc = document.implementation.createHTMLDocument(""); doc.documentElement.innerHTML = markup; return doc; } else if ('content' in document.createElement('template')) { // Template tag exists! let el = document.createElement('template'); el.innerHTML = markup; return el.content; } else { // Template tag doesn't exist! var docfrag = document.createDocumentFragment(); let el = document.createElement('body'); el.innerHTML = markup; for (let i = 0; 0 < el.childNodes.length;) { docfrag.appendChild(el.childNodes[i]); } return docfrag; } } 

要做到这一点尽可能less线,你可以包装上面的另一个div的内容,所以你不必循环或调用appendchild不止一次。 使用jQuery(正如你所提到的是允许的),你可以很快地创build一个未连接的DOM节点,并将其放置在片段中。

 var html = '<div id="main"><div>x</div><span>y</span></div>'; var frag = document.createDocumentFragment(); frag.appendChild($​(html)[0]); 
 var html = '<div>x</div><span>y</span>'; var frag = document.createDocumentFragment(); var e = document.createElement('i'); frag.appendChild(e); e.insertAdjacentHTML('afterend', html); frag.removeChild(e); 

像@ dandavis说的那样,使用模板标签有一个标准的方法。
但是如果你喜欢支持IE11,而且你需要parsing表格元素(如'td> test'),那么你可以使用这个函数:

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