在DocumentFragment中插入任意HTML
Inserting arbitrary HTML into a DocumentFragment
我知道最近已经讨论过将innerHTML
添加到文档片段中,并有望将其包含在DOM标准中。但是,在此期间,您应该使用什么变通方法?
也就是说,采用
var html = '<div>x</div><span>y</span>';
var frag = document.createDocumentFragment();
我想要div
和span
都在frag
里面,有一个简单的一行。
无循环的奖励积分。jQuery是允许的,但我已经尝试过$(html).appendTo(frag)
;CCD_ 6之后仍然是空的。
在现代浏览器中有一种不循环的方法:
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;
}
更新:我找到了一种更简单的方法来使用Pete的主要想法,它在组合中添加了IE11:
function fragmentFromString(strHTML) {
return document.createRange().createContextualFragment(strHTML);
}
覆盖率优于<template>
方法,并且在IE11、Ch、FF中测试良好。
提供现场测试/演示http://pagedemos.com/str2fragment/
目前,只使用字符串填充文档片段的唯一方法是创建一个临时对象,并循环遍历子对象以将它们附加到片段中。
- 由于它没有附加到文档中,因此不会呈现任何内容,因此不会影响性能
- 你看到了一个循环,但它只循环通过第一个孩子。大多数文档只有几个半根元素,所以这也没什么大不了的
如果您想创建一个完整的文档,请改用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);
}
一行(两行可读)(输入: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中的自定义元素将立即随范围升级,但仅当使用模板克隆到真实文档中时。模板方法有点"惰性",这可能是可取的。
从来没有人提供过所要求的"简单的一行代码"。
给定变量…
var html = '<div>x</div><span>y</span>';
var frag = document.createDocumentFragment();
…下面的行就可以了(在Firefox 67.0.4中):
frag.append(...new DOMParser().parseFromString(html, "text/html").body.childNodes);
@PAEz指出@RobW的方法不包括元素之间的文本。这是因为children
只抓取元素,而不抓取Nodes。更稳健的方法可能如下:
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块可能会影响性能,但是,它与许多较旧的浏览器兼容,而且简洁。
var frag = document.createDocumentFragment();
var html = '<div>x</div><span>y</span>';
var holder = document.createElement("div")
holder.innerHTML = html
frag.appendChild(holder)
使用jquery,您只需将html保存并构建为字符串即可。如果你想把它转换成一个jquery对象来对它执行类似jquery的操作,只需执行$(html),它会在内存中创建一个jquery对象。一旦您准备好附加它,只需将它附加到页面上的现有元素即可
就像@dandavis所说的,有一种使用模板标记的标准方法
但是,如果您喜欢支持IE11,并且需要解析诸如"<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;
}
我会选择这样的东西。。
function fragmentFromString(html) {
const range = new Range();
const template = range.createContextualFragment(html);
range.selectNode(template.firstElementChild);
return range;
}
// Append to body
// document.body.append(fragmentFromString(`<div>a</div>`).cloneContents())
通过这种方式,您可以将内容保留在Range对象中,并免费获得所有所需的方法。
您可以在此处找到所有Range方法和属性的列表https://developer.mozilla.org/en-US/docs/Web/API/Range
注意:完成detatch()
方法后,请记住使用该方法,以避免泄漏并提高性能。
这是一个x浏览器解决方案,在IE10、IE11、Edge、Chrome和FF上进行了测试。
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; } }
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);
要用尽可能少的行来实现这一点,您可以将上面的内容包装在另一个div中,这样您就不必多次循环或调用appendchild。使用jQuery(正如您提到的那样),您可以非常快速地创建一个未连接的dom节点并将其放置在片段中。
var html = '<div id="main"><div>x</div><span>y</span></div>';
var frag = document.createDocumentFragment();
frag.appendChild($(html)[0]);
- 可以't让我的if语句处理js中的html表单输入
- 如何设置html元素填充的动画
- 使用JS如何动态更改显示的html文件中的文本背景颜色
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 我们可以使用任意的编程语言来动态化HTML页面吗
- 一个html/javascript'小工具'知道用户何时单击了小部件外的任意位置
- 用任意html替换ExtJS组件的内容
- 为任意html文档创建不引人注目的覆盖
- 是否可以使用HTML从任意字符串创建Jquery对象,例如var$newlink=$('<a>新链接
- 如何使用 AngularJS 向 HTML 标记添加任意属性
- 任意 JS/HTML 上传的 Web 安全性
- 在DocumentFragment中插入任意HTML
- Jquery使用自定义验证规则验证任意HTML元素
- 在javascript中从任意复杂的JSON对象生成html
- 从任意HTML表创建工具提示
- 如何从任意的html字符串中获得固定的html
- 如何在HTML's脚本标签中插入任意JSON
- 如何使用html画布绘制任意形状
- 如何更改 html 文本任意部分的样式
- JavaScript从任意URL的HTML内部获取一些信息