***什么是渲染树:
DOM树和CSSOM树结合。
***回流:
当渲染树(render tree)一部分(或全部)元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流。
每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的。
***如果再具体一点:
通过构造渲染树,我们将可见DOM节点以及它对应的样式结合起来,可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流。
为了弄清每个对象在网站上的确切大小和位置,浏览器从渲染树的根节点开始遍历。
***重绘:
当一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的。
比如background-color。这就叫称为重绘。
***区别与联系:
回流必将引起重绘,而重绘不一定会引起回流。
比如:只有颜色改变的时候就只会发生重绘而不会引起回流,
当页面布局和几何属性改变时就需要回流
***比如:添加或者删除可见的DOM元素,元素位置改变,元素尺寸改变——边距、填充、边框、宽度和高度,内容改变
***优化:
——首先我们要知道:由于浏览器每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。
浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。
但是!当你获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:
offsetTop、offsetLeft、offsetWidth、offsetHeight
scrollTop、scrollLeft、scrollWidth、scrollHeight
clientTop、clientLeft、clientWidth、clientHeight
getComputedStyle()
getBoundingClientRect
1:最好避免使用上面列出的属性,它们都会刷新渲染队列。
2:合并多次对DOM和样式的修改,然后一次处理掉(最小化重绘和重排)
可以这样:el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
也可以这样:el.className += ' active';
3:使元素脱离文档流(减少回流)
4:避免触发同步布局事件(访问元素的一些属性的时候,会导致浏览器强制清空队列,进行强制同步布局),例子:
不推荐写法:
function initP() {
for (let i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = box.offsetWidth + 'px';
}
}
推荐写法:
const width = box.offsetWidth;
function initP() {
for (let i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = width + 'px';
}
}
5:CSS3硬件加速(GPU加速)(根本不要回流重绘)
使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。
但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。
常见的触发硬件加速的css属性:transform,opacity,filters,Will-change
缺点:
如果为太多元素使用css3硬件加速,会导致内存占用较大,会有性能问题。
在GPU渲染字体会导致抗锯齿无效。这是因为GPU和CPU的算法不同。因此如果不在动画结束的时候关闭硬件加速,会产生字体模糊。
顺藤摸瓜(何为复合图层):
一般一个元素开启硬件加速后会变成复合图层,可以独立于普通文档流中,改动后可以避免整个页面重绘,提升性能
但是尽量不要大量使用复合图层,否则由于资源消耗过度,页面反而会变的更卡