IE使用documentFragment性能差

3
为了测试DOM操作与innerHTML之间的性能差异,我设计了这个小测试方法,使用一个documentFragment(网页)向一个div元素附加10000个href元素。在Chrome或Firefox中,性能还可以,但在IE(10、9、8)中,性能非常糟糕,需要大约10-12秒的时间。有人可以解释一下这种差异并/或详细说明提高IE性能的解决方案吗?
这里是一个jsfiddle演示它。
该方法:
function useFragment(){
    var frag = document.createDocumentFragment(),
        i = 10000,
        rval = document.createElement('span');
    frag.appendChild(rval);
    do {
     var optText = 'option '+i
        ,ref = document.createElement('a') 
        ,zebra = i%2 ? 'zebra' : ''
        ,islist = true
        ,isSel = i === 5
     ;
     rval.insertBefore(ref,rval.firstChild);
     ref.appendChild(document.createTextNode(optText));
     ref.id = 'opt' + i;
     ref.className = zebra + (islist && isSel ? ' scrollSelect' : '');
     ref.href = '#' + i;
     ref.title = optText;
   } while (i-->0);
   return rval;
}

我以前从来没有听说过文档片段... - John Dvorak
可能情况是如此(jsfiddle现在已经调整),但基本观点是IE在使用这种方法时非常、非常缓慢。除了IE庞然大物总是更慢,总需要微调才能使事情正常工作之外,我只是想不明白为什么。 - KooiInc
“Your measurements disagree…” => 这就是这个问题的关键 ;)它是更新的弹板基础版本。 - KooiInc
你仍然将 useInnerHtmlBttn.onclick 定义(以及许多其他可能在页面加载时异步发生的事情)包含在定时部分中。 - John Dvorak
使用http://jsfiddle.net/kW5dd/show/light/,并查看IE的分析器所显示的内容。 - KooiInc
显示剩余5条评论
2个回答

10

我想我找到了答案:尽管documentFragment应该是一个“离线”元素(即不是DOM的一部分),但 IE 并不会这样处理。强制使片段真正脱机的方法是将某个元素附加到它上面,将其 display 属性设置为 none,然后将其余元素附加到该元素上。完成后,删除display:none属性,然后就可以将documentFragment附加到DOM中了。

在我的电脑上,它仍然比 Chrome/Firefox 慢三倍(对于10000个元素,它仍然需要约1-1.5秒,而Chrome/Firefox只需大约2-300毫秒)。因此,在IE(甚至版本10)中使用 innerHTML 向DOM添加一堆元素是更快的方法。我认为,IE 仍然是开发人员的噩梦。


0
就我的经验而言,最好的好处是将许多孤立的元素附加到片段中,并在所有子元素和属性都固定(后附加)之前附加该元素。 如果我理解你的代码(我真的很懒得解码它),你附加到片段中的只有一个span。这不是documentFragment的意义所在。顺便说一下:你不应该在循环中声明变量。
var node=document.getElementById("whatever")
   ,frag=document.createDocumentFragment()
   ,i=0,len=50,a={},img={};
for(i;i<len;i++){
   a=document.createElement("a");
   img=document.createElement("img");
   a.href="image"+i;
   img.className=J[i][1];
   img.src="image/img"+i+".png";
   img.alt="image:"+i;
   a.appendChild(img);
   frag.appendChild(a);
   }                     
node.appendChild(frag);

这种方法IE8 Opera12所需的时间与innerHTML相当。真正的好处在于chrome。 FF使用innerHTML非常快。 在旧的XP计算机上进行了测试。

另一件要考虑的事情是创建一个未连接到DOM的节点,带有所有子元素和属性,然后将其多次克隆,操纵它并将其附加到documentFragment中。

var frag=document.createDocumentFragment()
   ,toFill=document.getElementById("imageCollection")
   ,i=0,a={},img={}
   ,dummy=document.createElement("a")
   ;
dummy.innerHTML="<img src='img/image_' />";   
for(i;i<50;i++){
   a=dummy.cloneNode(true);
   img=a.getElementsByTagName("img")[0];
   a.href="description_"+i+".html";
   img.src+=i+".png";
   frag.appendChild(a);
   }            
toFill.appendChild(frag);   

如果您不需要對克隆節點進行大量操作,這非常有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接