将 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&lt;div&gt;

(顺便说一句,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 您是否希望在 没有 innerHTMLinnerHTML 的情况下反序列化字符串?跨度> 嗯,是的,如果有其他方法可以利用浏览器的 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
&lt;div id="test"&gt;&lt;/div&gt;

【讨论】:

问题是关于追加,而不是替换

以上是关于将 HTML 字符串附加到 DOM的主要内容,如果未能解决你的问题,请参考以下文章

Python Flask将所有字符串附加到DOM

将 </> 文本附加为 html 时,它不会加载到 DOM [关闭]

更好的是,通过 DOM 函数附加新元素,或附加带有 HTML 标签的字符串?

jQuery 在附加到 DOM 之前从元素中生成变量

将 onDomContentLoaded 函数调用附加到 HTML 文件中的 DOM 对象

html 演示基于预先存在的ID将数据附加到DOM元素