重绘(repainting):元素样式发生改变,但宽高、大小、位置等不变;
如:color、background-color属性
回流(layout):元素的大小或者位置发生了变化(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染。
如:添加或删除可见的DOM元素;元素的位置发生变化;元素的尺寸发生变化;内容发生变化;页面一开始渲染的时候(这个无法避免);因为回流是根据视口的大小来计算元素的位置和大小的,所以浏览器的窗口尺寸变化也会引发回流。
注意:回流一定会触发重绘,而重绘不一定触发回流
回流和重绘都会影响性能,尤其是回流,所以第二条优化法则:尽可能减少避免DOM的重绘和回流。
如何避免/减少DOM回流?
1.放弃传统操作dom的方法,基于vue/react数据绑定视图模式(MVVM)
涉及知识点:MVVM/MVC/virtual dom/dom diff算法等
2.分离读写操作(现在浏览器都有渲染队列的机制)
// 连续写入,触发了渲染队列,仅回流一次
let box = document.getElementById('box')
box.style.width='200px'; // 写
box.style.height='200px'; // 写
// 读操作打断了渲染队列,会触发两次回流
let box = document.getElementById('box')
box.style.width='200px'; // 写
console.log(box.clientWidth); // 读
box.style.height='200px'; // 写
当下一行代码有这些时,及时下一行是修改样式,也会直接渲染执行回流:
offsetTop、offsetLeft、offsetWidth、offsetHeight、clientTop、clientWidth、clientHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、getComputedStyle、currentStyle...会刷新渲染队列
3.样式通过定义统一类的方式批量处理
4.尽量在dom树的最末端改变class
5. 缓存布局信息
// 因为每一行有clientWidth、clientHeight 所以还是会执行两次回流
box.style.width = box.clientWidth +10 +'px';
box.style.height= box.clientHeight +10 +'px';
// 仅执行一次
let a=box.clientWidth
let b=box.clientHeight
box.style.width = a+10 +’px’;
box.style.height= b+10 +’px’
6.元素批量修改
当使用js动态在ul中加入5个li时:
// 每循环一次就会想ul中加一个li子节点然后就会发生一次回流,一共执行了五次回流
for(let i=0; i<5;i++){
let newLi = document.createElement(‘li’)
newLi.innerHTML = i
box.appendChild(newLI)
}
// 方案一:使用文档碎片(临时容器)批量处理插入
let frg = document.createDocumentFragment();
for(let i=0; i<5;i++){
let newLi = document.createElement(‘li’)
newLi.innerHTML = i
frg.appendChild(newLI)
//创建的li放到文档碎片中,页面中还没有,所以不会执行回流
}
box.appendChild(frg) //一次性把内容放到box中,执行一次回流
frg=null //销毁,释放内存
// 方案二:字符串拼接
let str =``;
for(let i=0;i<5;i++){
str+=`<li>${i}</li>`
}
box.innerHTML = str;
7.动画效果应用到position为absolute或fixed等脱离文档流的元素上
它们不影响其他元素的布局,所它他们只会导致重新绘制,而不是一个完整回流。
8.开启css3硬件加速(GPU加速)
比如对元素应用3D变换。使用GPU可能会导致严重的性能问题,因为它增加了内存的使用,而且它会减少移动端设备的电池寿命。
transform: translate3d(0, 0, 0)
9.牺牲平滑度换取速度
10.避免table布局
- 根据Mozilla,即使一些小的变化将导致表格(table)中的所有其他节点回流;
- 因为table是个和罕见的可以影响在它们之前已经进入的DOM元素的显示的元素,table会因为某个单元格过宽导致整个纵列变化;
11.避免使用css的JavaScript表达式 (仅 IE 浏览器)
这项规则较过时
标签:box,style,渲染,元素,深入,回流,重绘 From: https://www.cnblogs.com/ligd2022/p/17046697.html