浏览器下载完所有组件(HTML、JS、CSS、Image)之后会解析生成两个内部数据结构:
DOM树、渲染树(帧、盒)
DOM变化->影响元素几何属性页面布局->浏览器重新计算:重排reflow;
重排之后,浏览器重新绘制受影响部分:重绘repaint。
重排何时发生:
1、添加或删除可见的DOM;
2、元素位置改变;
3、元素尺寸改变(padding、margin、border、width、height等);
4、内容改变;
5、浏览器窗口resize
6、滚动条出现触发整个页面的重排
渲染树变化的排队与刷新:
重排是通过队列化修改的,但是当执行offsetTop等、scrollTop等、clientTop等、getComputedStyle()需要立即执行触发重排获取正确的值。
最小化重绘和重排:
重绘重排代价可能会很昂贵,减少次数,应该合并多次DOM和样式的修改,然后一次性处理。
1、改变样式:比如分三次设置xxx.style.yyy,还不如一次性xxx.style.cssText="……"。或者就是直接加一个className。
2、批量修改DOM:当要对DOM进行一系列操作时,可以
(1)使元素脱离文档流:隐藏/显示、document fragment、拷贝到脱离文档的节点后再复制;
(2)对其应用多重改变;
(3)把元素带回文档中。
隐藏/显示:
var ul = document.getElementById('mylist');
ul.style.display="none";
appendDataToElement(ul,data);
ul.style.display = "block";
document fragment(推荐):
var fragment = document.createDocumentFragment();
appendDataToElement(fragment,data);
document.getElementById(mylist').appendChild(fragment);
拷贝到脱离文档的节点后再复制:
var old = document.getElementById('mylist');
var clone = old.cloneNode(true);
appendDataToElement(clone,data);
old.parentNode.replaceChild(clone, old);
让元素脱离动画流
比如展开/收起来显示和隐藏页面的一部分是一种常见的交互,它会把页面其他部分推向下方,当页面顶部的一个动画推移页面整个余下部分,在节点规模很大的情况下回导致一次大规模重排,造成一顿一顿。如何避免?
1、使用绝对定位,脱离文档流;
2、让元素覆盖部分页面,动起来;
3、结束时再恢复正常定位。