重绘和重排

751 阅读2分钟

1.重绘 一个元素外观发生改变所触发的浏览器行为,浏览器会根据元素的新属性来重新绘制,使元素呈现新的外观(但宽高。大小,位置等不变) 触发重绘的条件是改变元素的外观 

2.重排(回流,重构) 元素的大小或者位置发生了变化 当渲染树的一部分因为元素的规模尺寸,布局隐藏等改变而需要重新构建的时候,称做重构。 每个页面至少需要一次回流,就是在页面第一次加载的时候。 

触发重排的条件:任何页面布局和几何属性的改变都会 触发重排(其中页面的初始化触发的重排不可避免) 

 因为有重绘和重排这种机制,他们会影响性能,所以前端优化又变成非常重要的话题。 

 如何进行前端性能优化? 

 1. 避免DOM的回流 放弃传统的操作dom的时代,基于vue/react开始数据影响视图模式 mvvm/mvc/virtual dom/dom diff 

 2. 分离读写操作(现代的浏览器都有渲染队列的机制) 当代浏览器会维护一个队列,把所有会引起回流重拍的操作放入这个队列,等队列中的操作到达一定数量或者到了一定的时间间隔,浏览器就会维护队列, 进行一个批次处理,这样会让多次回流变成一次回流。当时如果在连续的回流操作中间插一条读取操作就会,中断连续的批次操作处理。 所以我们推崇将写操作和读取操作分离开来,都改完样式之后,在后面读取操作。

3. 样式集中改变,批量操作。可以写一个样式类比如

.aa{
width:200px;
height:200px;
background-corlor:red;
}
box.className = "aa"
缓存处理:
let width = box.clientWidth;
let height = box.clientHeight;
boxWidth = width + '10' + 'px';
boxheight = height + '10' + 'px';
文档碎批量处理
let frg = document.createDocumentFrament();
for(let i = 0; i < 5; i++){
let newLi = document.createElement('li');
newLi.innerHTML = i;
frg.appendChild(newLi);
}
//一次性把内容放到容器中,引发一次回流
box.appendChild(frg);
//但是现在这种方式我们不常用了,因为我们有了模版字符串
let str = '';
for(let i = 0; i < 5; i++){
str += `
  • ${i}
  • `
    }
    box.innerHTML = str;

    动画效果应用到position: absolute/fixed(脱离文档流,减少回流)

    CSS3硬件加速(GPU加速)transform\opacity\filters 这些属性会触发硬件加速,不会触发回流和重绘。

    可能会有的坑:过多的使用会占用大量内存,性能消耗严重,有时候会导致字体模糊。
    避免table布局和食用css的js表达式