raf节流
目录
- 定时器节流
- Raf节流
- 介绍requestAnimationFrame
- 使用raf节流
- 注意点
- 对比
定时器节流
原理:setTimeout 节流的核心思想是通过定时器来控制函数的执行频率。当事件触发时设置定时器,当定时器结束后才能再次触发
Raf节流
介绍requestAnimationFrame
window.requestAnimationFrame()告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
使用raf节流
实际中 test函数可以为 渲染固定个数虚拟dom等
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="start">start</button><button id="end">end</button>
</body>
<script>const log=raf()document.getElementById('start').addEventListener('click',log.start)document.getElementById('end').addEventListener('click',log.end)function raf(){let bool=falselet num=0function test(){console.log([num++,Date.now()])if(bool){requestAnimationFrame(test)}}return {start(){if(bool) returnbool=truerequestAnimationFrame(test)},end(){if(!bool) returnbool=false}}}
</script>
</html>
当屏幕刷新率为200hz


刷新200次经历了999ms
当屏幕刷新率为60hz


刷新60次经历967ms
即实现了在浏览器每帧之间调用test函数
注意点
-
当离开当前标签页(在后台时)时
requestAnimationFrame函数会被暂挂 避免不必要的渲染 -
test函数应该减少操作量
若在test中加入
for(let i=0;i<1000000000;i++){}

刷新一次就耗时200ms+
若继续扩增则会阻塞主线程导致浏览器卡死
对比
定时器过度渲染
如果使用 setInterval 或 setTimeout 来控制动画的更新频率可能会导致每 5 毫秒就进行一次 DOM 操作,然而,浏览器的渲染频率通常是每 16.6 毫秒(即每秒 60 帧)
即在两次浏览器渲染之间,可能会有多次 DOM 操作频繁触发回流和重绘。造成过度渲染
回流:浏览器重新计算dom元素的位置尺寸等
重绘:浏览器重新绘制dom元素的样式
raf渲染缺失
当俩帧之间执行过多操作时,导致主线程阻塞后浏览器帧率降低,从而出现渲染缺失。表现为动画卡顿或跳帧,影响用户体验。
| 特性 | setTimeout 节流 | requestAnimationFrame 节流 |
|---|---|---|
| 实现难度 | 简单 | 稍复杂 |
| 兼容性 | 好(所有浏览器) | 较好(现代浏览器支持) |
| 执行频率 | 最多每秒约 250 次 | 屏幕刷新率 |
| 性能优化 | 无特殊优化 | 与屏幕刷新同步,节能 |
| 延迟 | 可能延迟 | 低延迟,与屏幕刷新同步 |
| 适用场景 | 通用场景,如按钮点击、输入框输入等 | 动画、滚动、窗口大小调整等与屏幕刷新相关的场景 |
