JavaScript:将子项追加到元素

时间:2010-02-13 10:31:54

标签: javascript performance dom

以下哪种技术更好用户体验?

在这两个示例中,假设thumbContainer设置为document.getElementById('thumbContainer')的返回值,new Thumbnail(thumb).toXMLString()返回包含XHTML标记的字符串。

A)只需+= thumbContainer.innerHTML

for (thumb in thumbnails) {
    thumbContainer.innerHTML += new Thumbnail(thumb).toXMLString();
} 

B)或者将new Thumbnail(thumb).toXMLString()转换为DOM元素并使用appendChild

for (thumb in thumbnails) {
    var shell = document.createElement('div');
    shell.innerHTML = new Thumbnail(thumb).toXMLString();
    for (i = 0; i < shell.childElementCount; i++) {
        thumbContainer.appendChild(shell.children[i]);
    }
}

我已经使用了两者并得到了Firefox的投诉,我有一个长期运行的脚本,我想阻止它吗?

哪个循环不太紧密,允许UI在新元素添加到DOM时更新?

2 个答案:

答案 0 :(得分:10)

  

A)只需+ =使用thumbContainer.innerHTML

从不这样做。这必须将所有内容序列化为HTML,向其中添加一个字符串,然后将其全部解析。它很慢(在循环中执行它是特别糟糕的新闻)并且它将丢失所有JavaScript引用,事件处理程序等等

IE的insertAdjacentHTML将更有效地完成此操作。它也是HTML5的一部分,但尚未在其他地方广泛实施。

  

使用appendChild?

是的,没关系。如果你有一个很多的拇指,它将开始变慢(但不会像每次重新分析innerHTML那样糟糕)。在某些情况下,使DocumentFragment一次将多个元素插入容器子节点列表可能会有所帮助。将DocumentFragment与Range结合起来可以做得更多,但是由于IE的Range实现是如此StRange,因此难以兼容地编写。

无论哪种方式,因为您似乎没有对单个shell节点做任何事情,为什么不在解析之前简单地将所有thumbernail HTML字符串连接在一起?

  

for(shell.childNodes中的var child){

不要在序列类型上使用for..in,它不会按照您的想法执行。它仅用于对抗用作映射的Object。迭代Array或NodeList的正确方法是普通的for (var i= 0; i<sequence.length; i++)

答案 1 :(得分:6)

我个人更喜欢第二种方法(使用appendChild),因为你在文档树中添加新元素而不影响旧元素。

使用innerHTML + =新内容时,会影响旧内容,因为必须重新分配所有HTML(替换为包含旧代码和新代码的新HTML)。

但是,如果你想提高性能,我建议使用DocumentFragments。使用它们,您可以在文档树上只添加一个appendChild调用附加整组节点。值得一读:"DOM DocumentFragments" by John Resig,但问题并非如此,因为您将内容作为字符串获取,您必须先转换为DOM节点。

我的第二个建议是,创建一个HTML代码字符串,然后在临时容器上使用innerHTML将其转换为DOM节点

var htmlCode = "";
for (thumb in thumbnails) {
    htmlCode += new Thumbnail(thumb).toXMLString();
}
var element = document.createElement(htmlCode);
element.innerHTML = htmlCode; // ... and append all the elements to document, or thumbContainer.innerHTML += htmlCode;