为什么是“element.innerHTML + =”错误的代码?

我已经被告知不要使用element.innerHTML += ...来追加东西element.innerHTML += ...就像这样:

 var str = "<div>hello world</div>"; var elm = document.getElementById("targetID"); elm.innerHTML += str; //not a good idea? 

它有什么问题?我还有其他的select吗?

每次设置innerHTML ,都必须parsingHTML,构build一个DOM,并将其插入到文档中。 这需要时间。

例如,如果elm.innerHTML有成千上万的div,表,列表,图像等,那么调用.innerHTML += ...将导致parsing器重新parsing所有的东西 。 这也可能会破坏对已经构build的DOM元素的引用并导致其他混乱。 实际上,你所要做的就是在最后附加一个新的元素。

最好是调用appendChild

 var newElement = document.createElement('div'); newElement.innerHTML = '<div>Hello World!</div>'; elm.appendChild(newElement);​​​​​​​​​​​​​​​​ 

这样, elm的现有内容就不会被再次parsing。

注意: [某些]浏览器可能足够聪明,可以优化+=运算符,而不会重新parsing现有内容。 我没有研究过这个。

是的, elm.innerHTML += str; 是一个非常糟糕的主意。

典型的“浏览器必须重buildDOM”的答案确实不正义:

  1. 首先,浏览器需要浏览榆树下的每个元素,每个属性以及它们的所有文本和注释以及处理节点,然后转义它们来为您创build一个string。

  2. 然后你有一个很长的string,你要追加。 这一步是好的。

  3. 第三,当你设置innerHTML时,浏览器必须删除所有刚刚经过的元素,属性和节点。

  4. 然后parsingstring,从刚刚销毁的所有元素,属性和节点构build,创build一个大致相同的新DOM片段。

  5. 最后它附加了新的节点,还必须通过扫描所有的JavaScriptvariables来回收旧节点。

问题:

  • 某些属性可能不会被HTML所反映,例如, <input>的当前值将会丢失并重置为HTML中的初始值。

  • 如果在旧节点上有任何事件处理程序,则它们将被销毁,并且必须重新连接所有这些事件。

  • 如果你的js代码引用了任何旧节点,它们将不会被破坏,而是被孤立。 它们属于文档,但不在DOM树中。 当你的代码访问它们时,什么都不会发生,否则可能会引发错误。

  • 这两个问题意味着它是不友善的js插件 – 插件可能附加处理程序或记住旧的节点,并导致内存泄漏。

  • 如果您习惯使用innerHTML进行DOM操作,则可能会意外更改属性或执行其他您不想要的操作。

  • 你拥有的节点越多,效率越低,电池汁就越多。

总之,效率低下,容易出错,只是懒惰而不知情。


最好的select是Element.insertAdjacentHTML ,我没有看到其他的答案提到:

elm.insertAdjacentHTML( 'beforeend', str )

几乎相同的代码,没有innerHTML的问题。 没有重build,没有处理程序丢失,没有input重置,内存碎片较less,没有坏习惯,没有手动元素创build和分配。

它允许你将htmlstring注入一行中的元素,包括属性,甚至允许yow注入复合元素和多个元素。 它的速度得到了优化 – 在Mozilla的testing中,速度提高了150倍。

如果有人告诉你它不是跨浏览器,它是如此有用,它是HTML5 标准,并在所有浏览器中可用。

不要再次写elm.innerHTML+=

替代方法是.createElement() .textContent.appendChild() 。 如果你处理大量的数据,追加+=只是一个问题。

演示: http : //jsfiddle.net/ThinkingStiff/v6WgG/

脚本

 var elm = document.getElementById( 'targetID' ), div = document.createElement( 'div' ); div.textContent = 'goodbye world'; elm.appendChild( div ); 

HTML

 <div id="targetID">hello world</div> 

如果用户使用的是旧版本的IE(或者也许是新版本的,还没有尝试过),那么td上的innerHTML会导致问题。 IE中的表元素是只读的,tsk tsk tsk。

迈克的答案可能是更好的答案,但另一个考虑是你正在处理string。 在JavaScript中的string连接可能会非常慢,特别是在一些较旧的浏览器中。 如果您只是连接HTML中的小碎片,那么它可能不是显而易见的,但是如果您有页面的主要部分,您要重复添加某些内容,则很可能会在浏览器中看到明显的停顿。

我刚刚学会了为什么innerHTML不好,在下面的代码中,当你设置innerHTML chrome失去了onclick事件jsFiddle

 var blah = document.getElementById('blah'); var div = document.createElement('button'); div.style['background-color'] = 'black'; div.style.padding = '20px;'; div.style.innerHTML = 'a'; div.onclick = () => { alert('wtf');}; blah.appendChild(div); // Uncomment this to make onclick stop working blah.innerHTML += ' this is the culprit'; <div id="blah"> </div>