如何将setInterval倒计时代码改写为requestAnimationFrame实现
将setInterval倒计时替换为requestAnimationFrame实现方案
核心逻辑和原代码完全对齐:30秒倒计时每秒更新数值,结束后弹出done提示,无额外逻辑改动。
实现要点
requestAnimationFrame执行频率和屏幕刷新率绑定,不能通过回调执行次数计数,必须通过时间戳差值计算剩余时间,避免计时不准- 使用
performance.now()获取高精度时间戳,不受系统时间调整、页面后台节流影响,计时稳定性更高 - 倒计时归0时主动取消动画帧任务,避免内存占用
完整代码
let timer = ref(30) // 记录倒计时启动的初始时间戳 const startTimestamp = performance.now() let rafTaskId = null const countDownLoop = () => { // 计算已经流逝的毫秒数 const elapsedTime = performance.now() - startTimestamp // 换算为剩余整秒数,和原逻辑保持一致每秒更新一次展示值 const remainSeconds = Math.max(0, 30 - Math.floor(elapsedTime / 1000)) timer.value = remainSeconds if (remainSeconds === 0) { // 倒计时结束,取消帧任务,执行原有提示逻辑 cancelAnimationFrame(rafTaskId) alert('done') return } // 注册下一帧回调 rafTaskId = requestAnimationFrame(countDownLoop) } // 启动倒计时 rafTaskId = requestAnimationFrame(countDownLoop)
补充说明
- 如果是在Vue组件中使用,需要在组件卸载时主动清理任务的话,直接在
onUnmounted钩子中调用cancelAnimationFrame(rafTaskId)即可,和原clearInterval的清理逻辑一致 - 该实现不会出现原setInterval常见的累计漂移问题,即使页面被切到后台、主线程有长任务阻塞,回到页面后剩余时间计算依然准确
内容的提问来源于stack exchange,提问作者f0.c
相关产品推荐
相关产品推荐

