天天看点

最小化重绘和重排之批量修改DOM

批量修改DOM的出发点是减少重绘和重排次数,基本思路是当需要对DOM进行多种修改操作时,首先让DOM脱离文档流;然后让其进行批量修改,修改的过程不会触发浏览器重排和重绘;最后将修改后的DOM重新加入文档中。这样只会在DOM脱离和重新加入文档流时触发重排和重绘操作两次,对于批量修改这样的操作有效降低重排和重绘次数。

DOM脱离文档流的方法

  • 改变DOM元素的可见性:前边的博客已经提到隐藏的DOM节点不会出现在渲染树。因此可以先将需要修改的元素的display属性设为“none”,进行修改后再将其改为“block”等可见属性值。
  • 使用cloneNode()方法:cloneNode()可以实现DOM的深拷贝(参数设置为true);因此可以将需要修改的DOM节点先进行深拷贝,对深拷贝的备份进行修改,然后用其替换原DOM节点即可。
  • 利用DocumentFragment对象:DocumentFragment对象不包含在真实的文档流之中,因此对其修改不会触发热reflow和repaint。DocumentFragment对象是一个无父节点的最小化文档对象,是一个轻量级的存储一段包含多个节点的文档结构。当将该对象插入DOM树时,其通常会将其子孙节点一并插入。可以使用createDocumentFragment创建该对象,然后使用appendChild等方法插入到DOM树。

代码示例

//方法一: 隐藏并修改后显示
var ele = document.getElementById('mylist');
ele.style.display = "none";
appendDataToElement(ele, data);
ele.style.display = "block";

//方法二:clone
var old = document.getElementById('mylist');
var clone = old.cloneNode(true);
appendDataToElement(clone, data);
old.parentNode.replaceChild(clone, old);

//方法三
var fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
document.getElementById('mylist').appendChild(fragment);    
           

References

  • MDN-createDocumentFragement
  • MDN-DocumentFragement Object
  • 高性能JavaScript(2015年8月第一版)

继续阅读