在网页的渲染过程中,"重绘"(Repaint)和"回流"(Reflow,也称为重排,Layout)是两个关键的概念,它们与浏览器如何显示页面内容有关。
### 回流(Reflow)
回流指的是当浏览器为了重新渲染部分或全部文档,需要重新计算元素的位置和几何形状时的过程。这通常发生在以下情况:
- 页面的首次加载。
- 浏览器窗口大小发生改变。
- 元素的内容发生变化(比如文本变化或图片被加载)。
- 元素的样式属性被修改(例如宽度、高度、位置等影响布局的属性)。
- 添加或删除可见的DOM元素。
由于回流涉及到元素尺寸和位置的重新计算,因此它比重绘更加耗时,尤其是当一个元素的变化导致其子元素、后续兄弟元素甚至祖先元素都需要重新布局时。
### 重绘(Repaint)
重绘是指当元素的外观(如颜色、背景色等不涉及尺寸和位置的属性)发生变化但不影响布局时,浏览器对元素进行重新绘制的过程。这意味着只有元素的视觉表现改变了,而不需要重新计算其尺寸和位置。重绘通常发生在以下情况下:
- 改变元素的颜色、透明度等视觉属性。
- 改变某个元素的可见性(`visibility`),但不包括`display:none`或`visibility:hidden`(后者会导致回流)。
虽然重绘相对于回流来说开销较小,但如果在一个页面上频繁触发重绘操作,仍然可能会影响到性能,特别是对于那些复杂的视觉效果。
### 总结
- **回流**:更侧重于布局的更新,任何引起页面布局变化的操作都会导致回流。这是一个相对昂贵的操作,因为它可能引发整个页面的重新布局。
- **重绘**:则是关于视觉上的更新,仅限于那些不会影响元素布局的属性。相比回流,它的开销较低,但仍然需要注意避免不必要的重绘以提高页面性能。
优化网站性能的一个重要方面就是尽量减少回流和重绘的次数。例如,通过批量修改DOM或者使用CSS3硬件加速等技术来降低这些操作的影响。
减少页面的回流(Reflow)和重绘(Repaint)是优化网页性能的重要手段。以下是一些常见且有效的优化策略,帮助你减少不必要的回流和重绘:
---
### 1. **避免频繁操作 DOM**
- **批量修改 DOM**:
- 尽量将多个 DOM 操作合并为一次操作,而不是逐个修改。
- 使用 `DocumentFragment` 或直接操作字符串模板,最后一次性插入到 DOM 中。
```javascript
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.textContent = `Item ${i}`;
fragment.appendChild(div);
}
document.body.appendChild(fragment); // 批量插入
```
- **使用 `innerHTML`**:
- 直接拼接 HTML 字符串并通过 `innerHTML` 插入,比多次调用 `appendChild` 更高效。
```javascript
let html = '';
for (let i = 0; i < 100; i++) {
html += `<div>Item ${i}</div>`;
}
document.getElementById('container').innerHTML = html;
```
---
### 2. **避免触发回流的操作**
- **避免频繁读取布局属性**:
- 读取某些布局属性(如 `offsetWidth`、`offsetHeight`、`getComputedStyle` 等)会强制浏览器进行回流以确保返回最新值。
- 如果需要读取多个布局属性,尽量缓存结果,避免重复触发回流。
```javascript
const width = element.offsetWidth; // 触发一次回流
const height = element.offsetHeight; // 不再触发回流
console.log(width, height);
```
- **避免动态更改布局相关的样式**:
- 避免在循环中频繁修改 `width`、`height`、`margin`、`padding` 等影响布局的属性。
---
### 3. **使用 CSS 动画代替 JavaScript 动画**
- **启用硬件加速**:
- 使用 CSS 的 `transform` 和 `opacity` 属性来实现动画,因为它们不会触发回流或重绘,而是由 GPU 加速渲染。
```css
.animate {
transition: transform 0.5s ease;
}
.animate.move {
transform: translateX(100px);
}
```
- **避免使用 `top`、`left` 等属性**:
- 修改 `top` 和 `left` 会导致回流,推荐使用 `transform: translate()`。
---
### 4. **使用 `visibility` 而非 `display`**
- **隐藏元素时**:
- 使用 `visibility: hidden` 只会触发重绘,而不会触发回流。
- 使用 `display: none` 会触发回流,因为它完全从文档流中移除元素。
---
### 5. **使用 `requestAnimationFrame`**
- **优化动画**:
- 在动画中使用 `requestAnimationFrame`,可以确保动画在浏览器的下一帧中执行,避免不必要的回流和重绘。
```javascript
function animate() {
element.style.transform = `translateX(${x}px)`;
x += 1;
if (x < 100) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
```
---
### 6. **使用虚拟 DOM 或框架优化**
- **React/Vue/Angular 等框架**:
- 这些框架通过虚拟 DOM 技术减少了直接操作真实 DOM 的次数,从而降低了回流和重绘的频率。
- **手动优化更新逻辑**:
- 如果不使用框架,可以手动实现类似虚拟 DOM 的机制,先在内存中计算 DOM 更新,最后一次性应用到真实 DOM。
---
### 7. **分离读写操作**
- **避免同时读写布局属性**:
- 浏览器会尝试优化回流,但如果在同一代码块中既有读取又有写入布局属性的操作,可能会导致多次回流。
- 将读写操作分开:
```javascript
// 错误示例:读写交替可能导致多次回流
element.style.width = '100px';
console.log(element.offsetWidth);
element.style.height = '200px';
// 正确示例:先读取所有值,再写入
const width = element.offsetWidth;
element.style.width = '100px';
element.style.height = '200px';
```
---
### 8. **使用 `will-change` 提前优化**
- **提示浏览器优化**:
- 对于即将发生变化的元素,可以使用 `will-change` 属性告诉浏览器提前优化。
```css
.element {
will-change: transform, opacity;
}
```
- 注意不要过度使用 `will-change`,否则可能导致性能问题。
---
### 9. **减少复杂选择器**
- **优化 CSS 选择器**:
- 复杂的选择器(如多层嵌套)会增加浏览器的计算开销,导致回流和重绘变慢。
- 使用简单的类名选择器,例如 `.class`,而不是复杂的后代选择器。
---
### 10. **固定元素尺寸**
- **避免动态调整尺寸**:
- 如果可能,给元素设置固定的宽度和高度,避免动态调整导致回流。
- 对于需要动态调整的内容,可以使用 `min-width`、`min-height` 或 `overflow` 来减少对布局的影响。
---
### 11. **使用 `position: absolute` 或 `fixed`**
- **脱离文档流**:
- 使用 `position: absolute` 或 `position: fixed` 可以让元素脱离文档流,减少对其它元素布局的影响。
---
### 12. **延迟加载内容**
- **懒加载图片或组件**:
- 对于不在视口内的内容,可以使用懒加载技术,在用户滚动到相应位置时再加载,减少初始渲染的压力。
---
### 总结
通过以上方法,可以有效减少页面的回流和重绘,提升网页的性能。在实际开发中,可以通过浏览器开发者工具(如 Chrome DevTools 的 Performance 和 Rendering 工具)分析页面的回流和重绘情况,并针对性地优化代码。
和“回流“(Reflow&spm=1001.2101.3001.5002&articleId=147513804&d=1&t=3&u=a94fb48f52d4416089fcf6ce27d80382)
1582

被折叠的 条评论
为什么被折叠?



