本文作者:IMWeb yuchenli 原文出处:IMWeb社区 未经同意,禁止转载
创建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测试的结果是:
这里简单地通过createElement创建DOM是存在比较严重的性能问题的:
1、createElement本身就是不小的性能开支
2、 每次创建li元素都换插入到DOM中,会引起多次重排和重绘。
对面上面那种问题,可能就会想到通过innterHTML方式去创建DOM元素 这里先举个栗子:
var str = '';
for (t = 0; t < num; t++) {
str += `<li><li>`;
}
list = str;
测试结果如下:
相比之前的createElement方式性能提升了很多,不过这种方式仍然存在弊端:不方便获取创建的li元素,你不得不要等它渲染完成时,再去获取它。
cloneNode是用于克隆节点的,相比直接调用createElement创建DOM元素而言,它所花费的开销会更小些,就好比:读书的时候,抄作业要比做作业的容易的多。
举个栗子:
var li = document.createElement('li');
for (t = 0; t < num; t++) {
var cloneLi = li.cloneNode();
list.appendChild(cloneLi);
}
测试结果:
从结果中看出,cloneNode虽然比createElement快,但是还是不。那么还有没有更快的方式去创建DOM元素呢?接下来先介绍一个东西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);
我们完全没有必要按照上面的方式,通过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));