前言
最近写的都是写基础知识,为了提高巩固自己的知识体系,抽空就总结或复习一个知识点。为了防范于未然,说不定哪天就得重新找工作了。如何提高渲染时间,优化前端性能,必有减少重绘和重排。之前在前端性能优化上叶有介绍到这个。这篇文章系统性总结一下。
概念
重绘(Repainting)和重排(Reflow)是与网页渲染和布局有关的两个关键概念,它们在前端性能优化中非常重要。
- 重排(Reflow):
- 页面首次加载时,因为需要计算和布局整个文档。
- 当用户调整浏览器窗口大小。
- 当DOM结构发生变化,例如添加、删除或修改元素。
- 当元素的样式属性发生变化,如修改元素的宽度、高度、边距、填充、字体大小等。
- 重排是指浏览器重新计算并重新布局网页中的元素的过程,以确定它们的几何尺寸和位置。这通常发生在以下情况下:
- 重排是一项昂贵的操作,因为它会影响整个页面的布局,然后会触发重绘。
- 重绘(Repainting):
- 当元素的视觉属性发生变化,如颜色、背景、边框、阴影、文字内容等。
- 重绘是指在不改变元素的几何布局(尺寸和位置)的情况下,浏览器重新绘制元素的过程。这通常发生在以下情况下:
- 重绘比重排轻量,因为它不需要重新计算布局。
它们的关系是重排一定会触发重绘, 重绘不一定触发重绘。
触发时机
重绘(Repainting)和重排(Reflow)在网页中的触发时机有很多情况,通常是由DOM操作、CSS属性变化或浏览器事件等触发的。下面是一些触发重绘和重排的常见情况:
重排(Reflow)的触发时机:
- 页面首次加载:当浏览器首次加载页面时,需要进行初始的布局计算,这会导致重排。
- 改变窗口大小:当用户调整浏览器窗口大小时,页面的布局会发生变化,触发重排。
- 修改DOM结构:添加、删除或更改页面上的元素、文本内容或其结构,通常会触发重排。
- 修改样式属性:当元素的CSS样式属性发生变化,如宽度、高度、边距、填充、字体大小等,会引起重排。
- 获取某些布局属性:访问一些需要计算布局属性的方法,如
offsetTop
、offsetLeft
、offsetWidth
、offsetHeight
、clientTop
、clientLeft
、clientWidth
、clientHeight
等,会触发重排。 - 字体加载:当网页中使用的字体在加载完成之前会导致重排。
重绘(Repainting)的触发时机:
- 改变颜色、背景、边框:当元素的颜色、背景、边框等视觉属性发生变化时,会触发重绘。
- 文本内容变化:当元素的文本内容变化,例如修改文字或标签文本,会触发重绘。
- 阴影、透明度等样式变化:改变元素的阴影、透明度、文本阴影等视觉属性会引发重绘。
浏览器优化
现在的Web浏览器都具有各种优化机制,旨在提高性能、提升用户体验以及降低资源消耗。以下是一些常见的浏览器优化机制:
- 页面缓存: 浏览器会缓存页面的静态资源,例如CSS文件、JavaScript文件和图片,以减少重复下载的次数。这可以提高页面加载速度,特别是在用户再次访问相同页面时。
- HTTP缓存: 浏览器支持HTTP缓存,它允许服务器指定哪些资源可以在客户端缓存多长时间。这减少了对服务器的请求,提高了页面加载速度。
- 预加载: 现代浏览器可以通过预加载机制在用户导航到某个链接之前预先加载页面的资源,以提前准备数据,加快导航速度。
- DOM解析和渲染优化: 浏览器会尝试尽早开始DOM解析和渲染,以提供更快的首次页面渲染。
- 异步加载: 使用
async
和defer
属性来异步加载JavaScript文件,以避免阻塞页面的渲染和提高性能。 - 图片延迟加载: 延迟加载图片,只在用户滚动到可见部分时加载,以减少页面初次加载时间。
- 硬件加速: 浏览器可以利用计算机的GPU来加速图形渲染,从而提高性能,特别是在处理复杂动画和3D效果时。
- 预渲染和预取: 浏览器可以根据用户的行为预先加载链接或页面,以提供快速导航体验。
- 资源压缩: 浏览器支持gzip等压缩方法,以减小传输的数据大小,减少网络带宽消耗和提高加载速度。
- 资源合并和减少请求数: 通过合并CSS和JavaScript文件、使用雪碧图、减少HTTP请求等方法,减少请求数,从而加快页面加载速度。
如何减少重绘重排
避免肯定是不可能的,所以为了优化渲染过程,提高用户体验,在平时的开发过程中要尽可能减少重绘重排。以下是一些减少重绘和重排的实用方法:
- 使用硬件加速: 使用 CSS 属性
transform
和opacity
可以触发硬件加速,减少重排和重绘的开销。例如,使用transform
进行动画而不是修改元素的位置。 - 使用 requestAnimationFrame: 使用
requestAnimationFrame
来调度动画操作,它可以确保动画在浏览器的下一次绘制帧之前进行,以避免不必要的重绘。 - 使用 CSS 动画: 使用 CSS 动画而不是JavaScript动画,因为浏览器可以优化CSS动画,减少对页面的影响。
- 批量DOM操作: 避免多次单独的DOM修改。相反,尽量将多个DOM操作合并成一个,然后一次性进行处理。
- 避免频繁读取布局属性: 避免在循环中多次读取布局属性,因为每次读取都会导致重排。将布局属性的值缓存到变量中,以减少性能开销。
- 使用文档碎片(Document Fragments): 如果需要创建大量DOM元素,使用文档碎片可以减少DOM操作次数,从而减少重排。
- 延迟加载图片: 图片的加载是重排的常见原因。通过延迟加载图片,只在它们进入视口时加载,可以减少页面加载时的性能开销。
- 避免表格布局: 表格布局的改变通常会导致整个表格的重排,尽量避免使用表格布局。
- 使用CSS属性
will-change
: 使用will-change
属性可以告诉浏览器某个元素可能会发生变化,从而使浏览器能够做出优化。 - 减少重排的影响范围: 如果不是整个页面的布局都发生了变化,可以尝试减小重排的影响范围,只重新布局受影响的部分。
- 使用工具进行性能分析: 使用浏览器的开发者工具来分析页面的性能,找出触发重排和重绘的问题,并进行优化。