Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

添加元素的性能瓶颈

  大家都知道DOM操作效率低,要创建大量元素当然也是个效率很低的行为。但由于创建元素和放入文档的方式有很做种,所以人们总是想从中做一些优化来提高DOM操作的效率。这些方法自身确实存在优缺点,但是DOM操作的瓶颈未必真在DOM上。
  我们先来看看这些DOM操作相关的方法吧
  createElement
  它的优点是创建的对象可以保存下句柄以备未来使用。在需要一次性创建大量元素的场合,那些被创建的元素通常不会仅仅被作为展示数据用,更多的情况是被作为文档控制用。大多情况下这些被添加的节点在今后是需要用到的,所以使用createElement添加元素省去了以后再去从文档中寻找这些元素的麻烦。
  appendChild、insertBefore
  调用createElement只是在文档外创建了一个元素,还需要调用这些方法把它放入文档内。
<script>
addEventListener("load",function(){
  var t,i,div;
  t=new Date;
  for(i=0;i<1E4;i++){
    div=document.createElement("div");
    document.body.appendChild(div);
  };
  setTimeout(function(){
    console.log(new Date-t);
  });
});
</script>
  createDocumentFragment
  当然我们也可以创建一个作为容器的元素来先在文档外把元素组织好后再把作为容器的元素放入文档中。这就有两个选择,一种是使用普通元素作为容器,这会带来额外的嵌套结构。或者使用文档片段(DocumentFragment)来作为临时元素。
<script>
addEventListener("load",function(){
  var i,t,m,div;
  t=new Date;
  m=document.createDocumentFragment();
  for(i=0;i<1E4;i++){
    div=document.createElement("div");
    m.appendChild(div);
  };
  document.body.appendChild(m);
  setTimeout(function(){
    console.log(new Date-t);
  });
});
</script>
  innerHTML、insertAdjacentHTML
  这两个方法是提供HTML文本让文档自己解析。它们同时包含了创建和放入文档的功能。但是我们无法在创建时获取到每个创建的元素对象,需要创建完之后再从文档中找出它们。对于将来不再需要单独操作创建元素的应用场合这个方法是很管用的。
<script>
addEventListener("load",function(){
  var t,data;
  t=new Date;
  data=Array(1E4+1).join("<div></div>");
  document.body.insertAdjacentHTML("beforeend",data);
  setTimeout(function(){
    console.log(new Date-t);
  });
});
</script>
  总之,能用到的大概就这么几种,实际上这些方式自身的性能差异并不大,关键在于应用的场合选择合适的方法。大家关心的主要是把元素添加到文档中的效率,这是很难确定的。因为把元素放入文档中本来是非常简单的工作,上面这个1E4的数量级瞬间就能完成,瓶颈不在于放入文档这个动作本身。文档操作是同步执行的,为什么我最后还要用异步来计算耗时呢?这就是因为影响性能的不是文档操作本身,而是文档操作之外的东西。我们把元素放入文档后CSS要计算它们自己和它们影响到的选择器值,然后它们自身和被他们影响的元素还要重新计算CSS的计算值,接着是Layout和Paint。这一系列过程才是影响性能的元凶,所以整个添加元素的性能问题得从CSS的方面考虑,而不是单纯的DOM操作问题。
网名:
3.80.32.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^