yuchenli

19 天前

如何更优地去创建DOM元素

本文作者:IMWeb yuchenli 原文出处:IMWeb社区 未经同意,禁止转载

如何更优地去创建DOM元素

创建DOM元素是最为基本的DOM操作,这里先举个栗子

这里先使用createElement创建了10个li元素

var list = document.querySelector('.list'),
    num = 10,;

for (t = 0; t < num; t++) {
   var li = document.createElement('li');
   list.appendChild(li);
}

measurethat测试的结果是:

image

这里简单地通过createElement创建DOM是存在比较严重的性能问题的:

1、createElement本身就是不小的性能开支

2、 每次创建li元素都换插入到DOM中,会引起多次重排和重绘。

innerHTM

对面上面那种问题,可能就会想到通过innterHTML方式去创建DOM元素 这里先举个栗子:

var str = '';
for (t = 0; t < num; t++) {
    str += `<li><li>`;
}
list = str;

测试结果如下:

image

相比之前的createElement方式性能提升了很多,不过这种方式仍然存在弊端:不方便获取创建的li元素,你不得不要等它渲染完成时,再去获取它。

cloneNode

cloneNode是用于克隆节点的,相比直接调用createElement创建DOM元素而言,它所花费的开销会更小些,就好比:读书的时候,抄作业要比做作业的容易的多。

举个栗子:

var li = document.createElement('li');
for (t = 0; t < num; t++) {
   var cloneLi = li.cloneNode();
   list.appendChild(cloneLi);
}

测试结果:

image

从结果中看出,cloneNode虽然比createElement快,但是还是不。那么还有没有更快的方式去创建DOM元素呢?接下来先介绍一个东西DocumentFragment

DocumentFragment

DocumentFragment是示一个没有父级文件的最小文档对象。它被当做一个轻量版的 Document使用,用于存储已排好版的或尚未打理好格式的XML片段。最大的区别是因为DocumentFragment不是真实DOM树的一部分,它的变化不会引起DOM树的重新渲染的操作,且不会导致性能等问题。考虑这个因素,我们可以结合cloneNode和DocumentFragment在去创建DOM元素并插入到文档:

var fragment = document.createDocumentFragment();
var li = document.createElement('li');
for (t = 0; t < num; t++) {
   var cloneLi = li.cloneNode();
   fragment.appendChild(cloneLi);
}
list.appendChild(fragment);

优化cloneNode+fragment

我们完全没有必要按照上面的方式,通过100次循环去将li放入fragment,因为fragment自身是可以被克隆的。利用这种特性,可以将100次循环降低到10次循环,具体的代码如下:

function cloneMultiple (elem, times, deep) {
   var fragment = document.createDocumentFragment();
   fragment.appendChild(elem.cloneNode(deep));
   if (times <= 1) {
       return fragment;
   }

   var i = 1,
       rest = [];

   while((times % 2 === 0 || !!(rest[i] = 1 && --times)) && (times /= 2) && times >3 ) {
        i += 1;  
   }

   while ( times > 1 ) {
      fragment.appendChild(elem.cloneNode(deep));
      --times;
   }

    for ( ; i; --i ) {
      fragment.appendChild(fragment.cloneNode(true));   
      rest[i] && fragment.appendChild(elem.cloneNode(deep));
    }

   return fragment;
}

 var li = document.createElement('li');
 list.appendChild(cloneMultiple(li, num, true));

最终测试结果

测试样例

image

0条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。