1.重绘 一个元素外观发生改变所触发的浏览器行为,浏览器会根据元素的新属性来重新绘制,使元素呈现新的外观(但宽高。大小,位置等不变) 触发重绘的条件是改变元素的外观
2.重排(回流,重构) 元素的大小或者位置发生了变化 当渲染树的一部分因为元素的规模尺寸,布局隐藏等改变而需要重新构建的时候,称做重构。 每个页面至少需要一次回流,就是在页面第一次加载的时候。
触发重排的条件:任何页面布局和几何属性的改变都会 触发重排(其中页面的初始化触发的重排不可避免)
因为有重绘和重排这种机制,他们会影响性能,所以前端优化又变成非常重要的话题。
如何进行前端性能优化?
1. 避免DOM的回流 放弃传统的操作dom的时代,基于vue/react开始数据影响视图模式 mvvm/mvc/virtual dom/dom diff
2. 分离读写操作(现代的浏览器都有渲染队列的机制) 当代浏览器会维护一个队列,把所有会引起回流重拍的操作放入这个队列,等队列中的操作到达一定数量或者到了一定的时间间隔,浏览器就会维护队列, 进行一个批次处理,这样会让多次回流变成一次回流。当时如果在连续的回流操作中间插一条读取操作就会,中断连续的批次操作处理。 所以我们推崇将写操作和读取操作分离开来,都改完样式之后,在后面读取操作。
3. 样式集中改变,批量操作。可以写一个样式类比如
| |||||||||||
| 缓存处理: | |
| 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 += ` | |
| } | |
| box.innerHTML = str; |
动画效果应用到position: absolute/fixed(脱离文档流,减少回流)
CSS3硬件加速(GPU加速)transform\opacity\filters 这些属性会触发硬件加速,不会触发回流和重绘。
可能会有的坑:过多的使用会占用大量内存,性能消耗严重,有时候会导致字体模糊。
避免table布局和食用css的js表达式