登录
首页 >  文章 >  前端

使用 ref 封装可复用计时器逻辑实战

时间:2026-04-07 21:10:15 226浏览 收藏

本文深入讲解了如何使用 Vue 的 ref 和组合式 API 封装一个高复用、健壮且灵活的计时器逻辑,不仅支持秒级/毫秒级精度、暂停/恢复/重置等完整控制能力,还内置响应式状态(timeLeft、isRunning)、进度计算(progress)以及自定义回调(onTick、onFinish),并通过 onUnmounted 自动清理定时器防止内存泄漏;封装后的 useTimer 可在验证码发送、活动倒计时、表单防抖等多种场景中即插即用,解构即用、零重复代码,是提升 Vue 项目可维护性与开发效率的实用利器。

如何用 ref 实现一个可复用的计时器逻辑?Composition API 封装实战

ref 实现可复用计时器逻辑,核心是把状态(如剩余时间、运行状态)和操作(启动、暂停、重置)封装进一个函数,返回响应式引用和控制函数,便于在多个组件中直接解构使用。

封装基础计时器:ref + setInterval

ref 管理时间值和开关状态,配合 onUnmounted 清理定时器,避免内存泄漏:

import { ref, onUnmounted } from 'vue'
<p>export function useTimer(duration = 60) {
const timeLeft = ref(duration)
const isRunning = ref(false)
let timer = null</p><p>const start = () => {
if (isRunning.value || timeLeft.value <= 0) return
isRunning.value = true
timer = setInterval(() => {
timeLeft.value--
if (timeLeft.value <= 0) {
clearInterval(timer)
isRunning.value = false
}
}, 1000)
}</p><p>const pause = () => {
if (isRunning.value) {
clearInterval(timer)
isRunning.value = false
}
}</p><p>const reset = (newDuration = duration) => {
pause()
timeLeft.value = newDuration
}</p><p>// 组件卸载时自动清理
onUnmounted(() => {
if (timer) clearInterval(timer)
})</p><p>return {
timeLeft,
isRunning,
start,
pause,
reset
}
}</p>

支持毫秒级精度与自定义回调

实际项目中常需更细粒度控制或触发副作用(如倒计时结束通知),可在封装中加入回调参数:

  • ref 存储毫秒级剩余时间(如 msLeft),提升精度
  • 接收 onTickonFinish 回调,在对应时机执行
  • setInterval 改为 setTimeout 递归调用,避免累积误差

扩展功能:可暂停/恢复的倒计时(含进度百分比)

若需展示进度条或动态计算完成比例,可额外暴露 progress 计算属性(注意:Composition API 中需用 computed):

import { ref, computed } from 'vue'
<p>// 在 useTimer 内部添加:
const progress = computed(() => {
return ((duration - timeLeft.value) / duration) * 100
})</p><p>return {
timeLeft,
isRunning,
progress, // 如 0~100 的数值
start,
pause,
reset
}</p>

在组件中使用:简洁解构,即插即用

无需额外逻辑,直接导入并调用,响应式变量自动更新 UI:

<script setup>
import { useTimer } from './useTimer'
<p>const { timeLeft, isRunning, start, pause, reset } = useTimer(30)</p><p>// 模板中可直接用 {{ timeLeft }}、{{ isRunning }}
</script></p><p><template>
<div>{{ timeLeft }}s</div>
<button @click="start" v-if="!isRunning">开始</button>
<button @click="pause" v-else>暂停</button>
<button @click="reset">重置</button>
</template></p>

不复杂但容易忽略细节:务必清理定时器、区分「暂停」和「停止」语义、根据场景选择秒级或毫秒级精度。封装后,同一个 useTimer 可在登录验证码、表单防抖、活动倒计时等多个场景复用。

今天关于《使用 ref 封装可复用计时器逻辑实战》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>