将 HTML 字符串附加到 DOM
Posted
技术标签:
【中文标题】将 HTML 字符串附加到 DOM【英文标题】:Appending HTML string to the DOM 【发布时间】:2011-11-11 17:26:33 【问题描述】:如何附加 html 字符串,例如
var str = '<p>Just some <span>text</span> here</p>';
发送到 ID 为 test
的 <div>
?
(顺便说一句,div.innerHTML += str;
是不可接受的。)
【问题讨论】:
【参考方案1】:使用insertAdjacentHTML
哪个is supported in all current browsers:
div.insertAdjacentHTML( 'beforeend', str );
位置参数beforeend
将添加到元素内部,在其最后一个子元素之后。
现场演示: http://jsfiddle.net/euQ5n/
【讨论】:
@alex 是同一个概念:解析 HTML 字符串并将其放入 DOM。但功能不同 -innerHTML
将字符串放入元素中(替换所有子元素),而 insertAdjacentHTML
将其 (1) 放在元素之前,(2) 元素之后,(3) 放在第一个元素之前的元素内子元素,或 (4) 在最后一个子元素之后的元素内。
@alex insertAdjacentHTML
比附加到innerHTML
更快,因为insertAdjacentHTML
不会序列化和重新解析元素的现有子元素。
另外,insertAdjacentHTML
维护更改的表单元素的值,而附加到 innerHTML
会重建元素并丢失所有表单上下文。【参考方案2】:
性能
AppendChild
(E) 在 chrome 和 safari 上比其他解决方案快 2 倍以上,insertAdjacentHTML
(F) 在 firefox 上最快。 innerHTML=
(B)(不要与 +=
(A) 混淆)是所有浏览器上的第二个快速解决方案,它比 E 和 F 更方便。
详情
在 Chrome 75.0.3770(64 位)、Safari 11.1.0 (13604.5.6)、Firefox 67.0.0(64 位)上设置环境 (2019.07.10) MacOs High Sierra 10.13.4
在 Chrome E 上(每秒 140k 次操作)最快,B (47k) 和 F (46k) 次之,A (332) 最慢 在 firefox 上 F (94k) 最快,然后 B(80k)、D (73k)、E(64k)、C (21k) 最慢是 A(466) 在 Safari 上 E(207k) 最快,然后是 B(89k)、F(88k)、D(83k)、C(25k),最慢的是 A(509)你可以在你的机器上重播测试here
function A()
container.innerHTML += '<p>A: Just some <span>text</span> here</p>';
function B()
container.innerHTML = '<p>B: Just some <span>text</span> here</p>';
function C()
$('#container').append('<p>C: Just some <span>text</span> here</p>');
function D()
var p = document.createElement("p");
p.innerHTML = 'D: Just some <span>text</span> here';
container.appendChild(p);
function E()
var p = document.createElement("p");
var s = document.createElement("span");
s.appendChild( document.createTextNode("text ") );
p.appendChild( document.createTextNode("E: Just some ") );
p.appendChild( s );
p.appendChild( document.createTextNode(" here") );
container.appendChild(p);
function F()
container.insertAdjacentHTML('beforeend', '<p>F: Just some <span>text</span> here</p>');
A();
B();
C();
D();
E();
F();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This snippet only for show code used in test (in jsperf.com) - it not perform test itself.
<div id="container"></div>
【讨论】:
可读性通常比性能更重要。但是感谢您的腿部工作。 @Jay 优化只应在需要时使用,并且通常必须有丰富的注释 使用 innerHTML 似乎不好,因为浏览器必须再次解析整个 HTML,而不是添加到尾部【参考方案3】:这可以接受吗?
var child = document.createElement('div');
child.innerHTML = str;
child = child.firstChild;
document.getElementById('test').appendChild(child);
jsFiddle.
但是,Neil's answer 是更好的解决方案。
【讨论】:
@Šime 使用 DOM API 总是 感觉就像是 hack :P 您是否希望在 没有innerHTML
innerHTML
的情况下反序列化字符串?跨度>
嗯,是的,如果有其他方法可以利用浏览器的 HTML 解析器,我很想知道...
@Šime - 我认为只有两种方法可以利用浏览器的 HTML 解析器,innerHTML 和 document.write。如果你认为 innerHTML 是一种 hack ...
@Alohci 还有另一种方式:insertAdjacentHTML
。
@Šime-谢谢。我找到了 WHATWG 版本。它在DOM Parsing and Serialization 规范中。它表明除了innerHTML 和insertAdjacentHTML,还有outerHTML,我认为还有createContextualFragment。【参考方案4】:
想法是在中间元素上使用innerHTML
,然后通过appendChild
将其所有子节点移动到您真正想要的位置。
var target = document.getElementById('test');
var str = '<p>Just some <span>text</span> here</p>';
var temp = document.createElement('div');
temp.innerHTML = str;
while (temp.firstChild)
target.appendChild(temp.firstChild);
这避免了清除 div#test
上的任何事件处理程序,但仍允许您附加 HTML 字符串。
【讨论】:
【参考方案5】:正确的方法是使用insertAdjacentHTML
。在 Firefox 8 之前的版本中,如果您的 str
不包含 script
标签,您可以回退到使用 Range.createContextualFragment
。
如果您的str
包含script
标签,则需要在插入片段之前从createContextualFragment
返回的片段中删除script
元素。否则,脚本将运行。 (insertAdjacentHTML
标记脚本不可执行。)
【讨论】:
感谢您提及createContextualFragment
。我一直在寻找一种方法,让一些带有脚本的 html 包含仅在用户同意设置 cookie 时才运行。【参考方案6】:
快速破解:
<script>
document.children[0].innerHTML="<h1>QUICK_HACK</h1>";
</script>
用例:
1:另存为 .html 文件并在 chrome 或 firefox 或 edge 中运行。 (IE 不会工作)
2:在http://js.do中使用
在行动: http://js.do/HeavyMetalCookies/quick_hack
用 cmets 分解:
<script>
//: The message "QUICK_HACK"
//: wrapped in a header #1 tag.
var text = "<h1>QUICK_HACK</h1>";
//: It's a quick hack, so I don't
//: care where it goes on the document,
//: just as long as I can see it.
//: Since I am doing this quick hack in
//: an empty file or scratchpad,
//: it should be visible.
var child = document.children[0];
//: Set the html content of your child
//: to the message you want to see on screen.
child.innerHTML = text;
</script>
我发帖的原因:
JS.do 有两个必备:
-
没有自动完成
垂直显示器友好
但不显示 console.log 消息。 来这里寻找快速解决方案。 我只想看看结果 几行暂存代码, 其他解决方案工作量太大。
【讨论】:
【参考方案7】:为什么不能接受?
document.getElementById('test').innerHTML += str
这将是教科书的做法。
【讨论】:
它会将kill event handlers 附加到#test
。这通常是不可取的。
有趣的是它这样做了。似乎真的不合逻辑。
如果您考虑将 HTML 序列化为字符串,然后将 HTML 设置回来,这是合乎逻辑的。
我想 javascript 必须再次运行才能重置事件处理程序。很公平。
@Nick 您不想将 DOM 的一部分进行字符串化(序列化),以便您可以将其与另一个字符串连接起来,然后将整个内容解析回 DOM。正如亚历克斯所说,序列化不会记录绑定的事件处理程序(除其他外)。即使他的序列化可以捕获所有内容,您仍然不想这样做。【参考方案8】:
这个可以解决
document.getElementById("list-input-email").insertAdjacentHTML('beforeend', '<div class=""><input type="text" name="" value="" class="" /></div>');
【讨论】:
欢迎来到堆栈溢出。请解释您的代码作为答案的一部分,以提供一些上下文,而不仅仅是粘贴一长串代码。虽然你理解它,但其他人可能不理解它在做什么。【参考方案9】:InnerHTML 清除现有节点的所有数据,如事件
append child with firstChild 仅将第一个子元素添加到 innerHTML。例如,如果我们必须附加:
<p>text1</p><p>text2</p>
只有 text1 会显示
这个呢:
通过追加子元素将特殊标签添加到innerHTML,然后通过删除我们创建的标签来编辑outerHTML。不知道它有多聪明,但它对我有用 或者您可以将outerHTML 更改为innerHTML,这样它就不必使用函数replace
function append(element, str)
var child = document.createElement('someshittyuniquetag');
child.innerHTML = str;
element.appendChild(child);
child.outerHTML = child.outerHTML.replace(/<\/?someshittyuniquetag>/, '');
// or Even child.outerHTML = child.innerHTML
<div id="testit">
This text is inside the div
<button onclick="append(document.getElementById('testit'), '<button>dadasasdas</button>')">To div</button>
<button onclick="append(this, 'some text')">to this</button>
</div>
【讨论】:
【参考方案10】:最短 - 18 个字符(不要混淆+=
(OP 提及)和=
更多详细信息here)
test.innerHTML=str
var str = '<p>Just some <span>text</span> here</p>';
test.innerHTML=str
<div id="test"></div>
【讨论】:
问题是关于追加,而不是替换。以上是关于将 HTML 字符串附加到 DOM的主要内容,如果未能解决你的问题,请参考以下文章
将 </> 文本附加为 html 时,它不会加载到 DOM [关闭]
更好的是,通过 DOM 函数附加新元素,或附加带有 HTML 标签的字符串?