重排和重绘
定义
前端的重排(Reflow
)和重绘(Repaint
)是与浏览器渲染页面相关的两个重要概念。它们都与DOM(文档对象模型)的结构和样式有关,但在执行的时机和代价上有一些不同。
- 重排(Reflow):
- 定义: 重排是指浏览器根据DOM结构和样式计算,重新计算元素的位置和大小,并确定它们在页面中的确切位置。
- 触发条件: 任何改变影响了页面布局的操作都可能导致重排,比如改变窗口大小、修改元素的样式、添加或删除DOM元素等。
- 代价: 重排的代价比较高,因为它涉及到整个页面布局的重新计算和重绘。
- 重绘(Repaint):
- 定义: 重绘是指在不改变页面布局的情况下,重新绘制元素的样式,比如颜色、背景等。
- 触发条件: 当改变了元素的样式但不影响布局时,会触发重绘。例如,修改了颜色、背景色等样式属性。
- 代价: 重绘的代价相对较低,因为它不涉及到整个布局的重新计算,只是重新绘制元素的外观。
优化
优化前端性能涉及到减少页面的重排和重绘次数,以及降低其影响。以下是一些从重排和重绘角度出发的优化策略:
1. 使用CSS3 动画和过渡:
- CSS3提供的动画和过渡效果使用硬件加速,减少对页面布局的影响,从而减少重排的次数。
css
// 不推荐的方式,触发重排和重绘
.element {
transition: width 0.3s ease-in-out;
}
/* 使用CSS3动画 */
.element {
animation: slide-in 0.5s ease-in-out;
}
@keyframes slide-in {
from { transform: translateX(-100px); }
to { transform: translateX(0); }
}
2. 避免频繁的样式改变:
- 尽量避免通过
JavaScript
直接操作样式,特别是在循环中。可以通过添加或删除类的方式进行样式的批量修改。
js
// 不推荐的方式,触发重排和重绘
for (let i = 0; i < 1000; i++) {
element.style.left = i + 'px';
}
// 推荐的方式,一次性修改样式
element.classList.add('move');
3. 使用文档片段:
- 当需要频繁操作DOM时,可以将操作放在文档片段(
DocumentFragment
)中,最后一次性添加到DOM中,减少触发重排和重绘的次数。
js
不推荐的方式,会导致多次重排和重绘
for (let i = 0; i < 1000; i++) {
document.body.appendChild(document.createElement('div'));
}
// 推荐的方式,一次性添加到DOM中
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const div = document.createElement('div');
fragment.appendChild(div);
}
document.body.appendChild(fragment);
4. 使用定位属性:
- 避免使用会导致整个文档流重新排列的属性,比如
position: absolute
。使用transform
和position: fixed
等属性可以减少重排的范围。
css
/* 避免使用 position: absolute,可能触发重排 */
.element {
position: absolute;
top: 10px;
left: 10px;
}
/* 推荐使用 transform,不会触发重排 */
.element {
transform: translate(10px, 10px);
}
5. 懒加载和虚拟列表:
- 对于大量数据,使用懒加载技术和虚拟列表,只渲染用户可见区域的内容,减少不必要的重排和重绘。
6. 合理使用 will-change 属性:
will-change
属性可以在元素即将发生变化之前提前通知浏览器,优化性能。
css
.element {
will-change: transform;
}
7. 使用批量样式修改方法:
- 将样式的修改放在一起执行,避免多次单独修改触发多次重排和重绘。
js
// 不推荐的方式,可能触发多次重排和重绘
element.style.width = '100px';
element.style.height = '100px';
element.style.background = 'red';
// 推荐的方式,一次性修改样式
element.style.cssText = 'width: 100px; height: 100px; background: red;';
通过结合使用这些优化策略,可以有效地减少页面的重排和重绘,提升前端性能。在实际应用中,需要根据具体情况权衡各种优化方法的使用,以达到最佳性能。
8. 缓存信息
在获取元素或浏览器宽高时可以进行缓存,或者一次性获取,而不是单独每次获取,因为每次获取都会进行一次重排,但如果已经重排后立即获取,是不会再次触发的