重绘:元素的样式改变(但是宽高,大小,位置等不变)
比如:outline, bisibility,color,background-color等位置大小没有变但是样式变了,引发重绘
回流(重排:理解为位置的重新排列):元素大小或者位置发生了改变(页面布局和几何信息发生了改变),触发了重新的布局,导致渲染重新计算布局和渲染。
比如:添加或者删除可见的DOM元素,元素的位置发生了变化,元素的尺寸发生变化,视口大小的变化;页面一开始渲染;
注意:回流一定会触发重绘,重绘不一定会触发回流
性能优化:
尽可能的减少DOM的回流和重绘(重排)
-
放弃传统的dom操作,基于vue/react开始数据影响视图
mvvm/mvc/virtual dom/ dom diff.....最大限度的减少操作DOM
-
分离读写操作(现代的浏览器有渲染队列机制)
offsetTop, offsetLeft, offsetWidth, offsetHeight
clientTop, clientLeft, clientWidth, clientHeight
scrollLeft, scrollTop, scrollWidth scrollHeight
getComputedStyle, currentStyle, 会刷新渲染队列
-
样式集中改变(批量处理)
box.style.cssText = '200'; box.className box.classList.add();// 定义好的样式
-
缓存布局信息
let a = box.clientHeight; let b = box.clientWidth; // box.style.width = box.clientWidth + 10 +'px' // box.style.height = box.clientHeigth + 10 + 'px' box.style.width = a + 10 + 'px'; box.style.height = b + 10 + 'px';
-
元素的批量修改
-
document.createDocumentFragment() 文档对象的容器
<ul id="box"> </ul> <script> let frag = document.createDocumentFragment(); for (let i = 1; i <= 5; i++) { let newLi = document.createElement('li'); newLi.innerText = i; frag.appendChild(newLi); } box.appendChild(frag); // 只触发一次回流 </script>
-
模板字符串拼接
<script> let str = ``; for (let i = 1; i <= 5; i++) { str += `<li> ${i}</li>`; } box.innerHTML = str; </script>
-
-
动画效果应用到position属性为fixed或者absolute上(脱离文档流,对其他的元素影响较小)
-
CSS3中的硬件加速
transform/opcacity/ filters ,这些回流不会引发回流和重绘
缺点:占用大量的内存,使字体模糊
-
牺牲平滑换速度
-
避免使用table布局和使用css的JavaScript表达式