记个笔记!
requestAnimationFrame是什么? 查看MDN
为什么这么做?有以下好处:
- 计时更准确,原生setInterval在执行过程中会产生时间偏差。(当然,也可以二次封装setInterval去除这个误差)
- 避免内存泄漏,在浏览器处于最小化状态或者切换到其他tab时(即当前网页处于不可见状态)原生setInterval依然会继续执行,造成内存泄漏;而requestAnimationFrame则没有这个问题,因为它是在浏览器下一次重绘之前执行传递的回调函数,当前网页不可见的时候,是不会进行重绘操作的,所以此时回调函数不会被执行。
- 不会丢帧,且性能更高,采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使动画卡顿不流畅
import { ref } from 'vue'
/**
* 用于替换原生setInterval
* @param fn 函数
* @param interval ms 执行间隔
* @return 函数 取消定时器的函数
* */
export function useInterval(fn: () => void, interval = 1000) {
let nowTime = ref(performance.now())
let preTime: number
let timeDifferance = 0 //每次的时间偏差
let timer: number
function refresh() {
preTime ??= performance.now()
if (preTime) {
nowTime.value = performance.now()
const realInterval = interval - timeDifferance
if (nowTime.value - preTime >= realInterval) {
timeDifferance = (nowTime.value - preTime - realInterval) % realInterval
preTime = performance.now()
fn()
console.log('时间误差:' + timeDifferance + 'ms')
}
}
timer = requestAnimationFrame(refresh)
}
timer = requestAnimationFrame(refresh)
// 立即执行
fn()
function cancelTimer() {
cancelAnimationFrame(timer)
}
// 离开后销毁
onUnmounted(() => {
cancelAnimationFrame(timer)
})
return cancelTimer
}
如果有什么疑问或者建议,可以多多交流,文笔有限,才疏学浅,文中若有不正之处,万望告知。
参考文档: