为什么是“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”的答案确实不正义:
-
首先,浏览器需要浏览榆树下的每个元素,每个属性以及它们的所有文本和注释以及处理节点,然后转义它们来为您创build一个string。
-
然后你有一个很长的string,你要追加。 这一步是好的。
-
第三,当你设置innerHTML时,浏览器必须删除所有刚刚经过的元素,属性和节点。
-
然后parsingstring,从刚刚销毁的所有元素,属性和节点构build,创build一个大致相同的新DOM片段。
-
最后它附加了新的节点,还必须通过扫描所有的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>