编程 如何在前端避免重排(Reflow)和重绘(Repaint)

2024-11-19 02:28:18 +0800 CST views 681

如何在前端避免重排(Reflow)和重绘(Repaint)

重排(Reflow)和 重绘(Repaint)是浏览器在处理页面渲染时的两大性能开销,频繁的重排和重绘会导致页面响应变慢、卡顿,影响用户体验。因此,减少和避免重排和重绘是前端优化的关键。

1. 避免重排(Reflow)

重排发生在当页面布局变化时,例如修改元素的尺寸、位置或在 DOM 中新增、删除元素。这是最消耗性能的操作之一。

1.1. 减少DOM操作

DOM 操作是引发重排的主要原因之一。尽量减少频繁的 DOM 结构变化,使用批量操作技术来减少性能损耗。

  • 方法:使用 DocumentFragment 或者一次性更新 DOM,避免逐个操作 DOM。
let fragment = document.createDocumentFragment();
let div = document.createElement('div');
fragment.appendChild(div);
document.body.appendChild(fragment);

1.2. 避免使用特定属性

有些属性会强制触发重排,例如:

  • offsetWidth
  • offsetHeight
  • scrollTop
  • clientWidth

在读取这些属性时,浏览器会立即重新计算页面布局,导致性能下降。避免频繁读取这些属性,或者缓存它们的值。

1.3. 使用CSS动画而非JavaScript

尽量使用 CSS 动画过渡效果 来代替 JavaScript 的样式变化,因为 CSS3 动画利用硬件加速,可以避免频繁触发重排。

1.4. 利用 position: absoluteposition: fixed

对于不需要参与页面文档流的元素,使用 position: absoluteposition: fixed,减少其影响其他元素的重排。

1.5. 使用 display: none

隐藏元素时,使用 display: none,它不会占据空间,也不会导致重排;相比之下,visibility: hidden 仅隐藏元素,但它仍然占据空间,可能引发页面重排。

1.6. 使用 requestAnimationFrame

将多个 DOM 操作放在 requestAnimationFrame 中,使浏览器可以在下一帧之前批量处理所有变更,减少中间无效的重排。

requestAnimationFrame(() => {
  // 批量处理 DOM 操作
});

2. 避免重绘(Repaint)

重绘是当元素外观发生变化时(如颜色、背景图像变化)浏览器需要重新绘制的过程,虽然它比重排消耗小,但频繁的重绘也会影响性能。

2.1. 使用 will-change 属性

will-change 告诉浏览器即将发生变化的样式,提前做好优化准备,减少不必要的重绘。

.element {
  will-change: transform;
}

2.2. 使用合成层

通过使用 translateZ(0)translate3d(0, 0, 0) 等属性将元素移入 GPU 加速的合成层,这样能将它们从主文档流中分离出来,避免影响其他元素。

.element {
  transform: translateZ(0);
}

2.3. 使用离屏Canvas

对于复杂的图形操作,可以先在离屏 Canvas 中绘制,再将结果绘制到屏幕上,避免频繁的重绘。

2.4. 使用 display: contents

display: contents 可以使元素只作为 DOM 容器存在,而不会在渲染树中产生任何视觉边界,从而减少不必要的重绘。

2.5. 使用 CSS 变量

使用 CSS 变量 可以减少重绘开销,尤其是在需要频繁改变样式时。

2.6. 避免昂贵的样式属性

尽量避免使用如 clip-pathfiltermix-blend-mode 等性能开销大的属性,因为它们可能导致大量重绘。


3. 总结

为了避免重排和重绘,以下几条策略非常关键:

  • 批量操作 DOM,尽量减少 DOM 操作次数。
  • 使用合成层,将频繁变化的元素放到单独的合成层。
  • 使用 will-change 提前通知浏览器进行优化。
  • 减少使用昂贵的 CSS 属性,例如 filterclip-path

通过这些优化技术,可以显著提高页面性能和用户体验。
images

复制全文 生成海报 前端开发 性能优化 网页设计

推荐文章

使用Vue 3实现无刷新数据加载
2024-11-18 17:48:20 +0800 CST
Vue3中如何处理跨域请求?
2024-11-19 08:43:14 +0800 CST
Elasticsearch 条件查询
2024-11-19 06:50:24 +0800 CST
html一个全屏背景视频
2024-11-18 00:48:20 +0800 CST
使用Rust进行跨平台GUI开发
2024-11-18 20:51:20 +0800 CST
记录一次服务器的优化对比
2024-11-19 09:18:23 +0800 CST
微信内弹出提示外部浏览器打开
2024-11-18 19:26:44 +0800 CST
html一个包含iPhoneX和MacBook模拟器
2024-11-19 08:03:47 +0800 CST
用 Rust 玩转 Google Sheets API
2024-11-19 02:36:20 +0800 CST
mysql int bigint 自增索引范围
2024-11-18 07:29:12 +0800 CST
资源文档库
2024-12-07 20:42:49 +0800 CST
PHP 唯一卡号生成
2024-11-18 21:24:12 +0800 CST
程序员茄子在线接单