性能优化——减少重绘重排
网页生成过程如下:
第四步:重新生成布局(重排)->修改布局
第五步:重新绘制(重绘)->修改颜色等样式,布局不变
减少重排和重绘的方法
- 使用 CSS3 动画和过渡效果:CSS3 动画和过渡效果可以利用 GPU 加速,减少对页面布局的影响,从而减少重绘和重排的次数。
<!-- HTML -->
<div class="box"></div>
/* CSS */
.box {
width: 100px;
height: 100px;
background-color: red;
transition: width 0.3s ease-in-out;
}
.box:hover {
width: 200px;
}
- 批量修改样式:对于需要修改多个样式属性的操作,可以将它们合并为一次操作,而不是多次单独操作。这样可以减少重绘和重排的次数。
- 使用文档片段(Document Fragment):在操作 DOM 时,可以使用文档片段来创建和修改 DOM 结构,然后将整个文档片段一次性添加到页面中。这样可以减少对 DOM 的多次修改,从而减少重绘和重排的次数。
- 缓存布局信息:在需要多次读取元素的布局信息(如宽度、高度、位置等)时,可以将这些信息缓存起来,避免多次触发重排。
// JavaScript
const element = document.getElementById('myElement');
const elementWidth = element.offsetWidth; // 缓存元素宽度
const elementHeight = element.offsetHeight; // 缓存元素高度
// 对 elementWidth 和 elementHeight 进行操作,不会引起重排和重绘
通过在需要多次访问元素宽度和高度的地方缓存这些信息,避免了多次触发重排
- 使用
transform
和opacity
进行动画:当需要对元素进行动画效果时,使用transform
属性和opacity
属性可以利用 GPU 加速,减少对布局的影响。
// JavaScript
function animateElement() {
const element = document.getElementById('myElement');
let position = 0;
function animate() {
position += 1;
element.style.transform = `translateX(${position}px)`;
if (position < 200) {
requestAnimationFrame(animate);
}
}
animate();
}
requestAnimationFrame
会在下一次浏览器重绘之前执行回调函数animate
,从而优化动画的性能。通过在每一帧中更新元素的transform
属性,我们可以实现平滑的位移动画,避免了不必要的重排和重绘。
- 避免频繁访问布局信息:避免在 JavaScript 中频繁访问元素的布局信息,因为每次访问都会触发重排。最好在一次操作中获取所需的布局信息,并将其缓存起来供后续使用。
- 可以使用
requestAnimationFrame
方法来优化动画的性能。它可以在下一次浏览器重绘之前执行操作,以避免不必要的重绘和重排。
调试技巧——Chrome DevTools
Element
- 输入字符串可以动态给元素添加类名
- 点击具体的样式可以实时预览
- 强制激活伪类
- 选中具有伪类的元素,点击:hov
- Dom树右键菜单 force state
Console
- console.log 灰色
- console.warn 黄色
- console.error 红色
- console.debug 蓝色
- console.info 白色
- console.table 具象化展示json
- console.dir 文件树
- 占位符 %s 字符串, %o 对象 ,%c 样式 ,%d 数字
Source
Performance
下面是一些常用的Performance API的方法和属性:
performance.timing
:包含了与页面加载和各个阶段相关的时间戳信息,如页面开始加载的时间、DOM准备完成的时间、脚本加载完成的时间等。可以使用这些时间戳来计算页面加载时间和各个阶段的耗时。performance.now()
:返回一个高精度的时间戳,通常用于测量和计算代码执行的时间。可以使用它来进行性能分析和优化,例如测量函数的执行时间。performance.mark()
和performance.measure()
:用于创建和测量自定义的性能标记。可以使用performance.mark()
在代码中插入标记点,然后使用performance.measure()
来测量两个标记点之间的时间差,从而获取代码片段的执行时间。performance.getEntries()
:返回一个包含所有已完成的性能条目的数组。每个性能条目都包含了与特定资源或行为相关的性能数据,如请求时间、响应大小、传输时间等。可以使用它来进一步分析和优化资源加载和网络请求等方面的性能。performance.memory
:包含了与内存使用相关的信息,如已分配的内存量、使用的内存量等。可以使用它来监控和分析网页的内存使用情况。
通过使用Performance API提供的方法和属性,可以对网页的性能进行监控、分析和优化。这样可以找到性能瓶颈,并采取相应的措施来提高网页的加载速度和响应性能,提升用户体验。