Vue 3 倒计时应封装为可控制、可监听、可复用、可销毁的自定义 Hook,核心是 ref 管理响应式秒数、onUnmounted 自动清理定时器,支持 start/pause/reset/isRunning 及 onTick/onComplete 回调。

Vue 3 中倒计时逻辑的通用封装,核心是利用 Composition API 抽离定时控制、状态响应和生命周期管理,避免重复写 setInterval、clearInterval 和手动清理逻辑。关键不是“写一个函数”,而是让倒计时具备可控制、可监听、可复用、可销毁的能力。
用自定义 Hook 封装基础倒计时能力
把倒计时抽象为「状态 + 行为」:剩余秒数是响应式数据,start/pause/reset 是操作方法。推荐使用 ref 管理秒数,onUnmounted 自动清理定时器,防止内存泄漏。
- 接收初始秒数(如 60),支持配置回调:
onTick(每秒触发)、onComplete(归零时执行) - 返回对象包含
counter(当前剩余秒数)、start、pause、reset、isRunning等字段 - 不自动启动,由组件按需调用
start(),更符合可控性原则
适配不同业务场景的扩展方式
单一 Hook 很难覆盖所有需求,可通过组合或参数增强灵活性:
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
- 需要毫秒级精度?传入
interval = 100并改用setTimeout递归模拟,避免setInterval累积误差 - 要对接服务端时间?在
start前先请求接口拿到目标时间戳,再计算本地剩余秒数,避免客户端时间不准问题 - 用于验证码按钮?加一个
isDisabled计算属性,配合v-if或:disabled控制按钮状态 - 需格式化显示(如
02:35)?在 Hook 内增加formattedTime计算属性,或由组件自行处理,保持职责分离
避免常见陷阱的实践要点
封装看似简单,但几个细节直接影响稳定性:
- 定时器变量必须用
let timer: NodeJS.Timeout | null = null显式声明,不可仅依赖闭包,否则热更新或多次调用易出错 - 暂停后重置,应先
clearInterval再赋新值,否则可能残留旧定时器 - 组件卸载时未清理 —— 一定要用
onUnmounted,不能只靠onBeforeUnmount,尤其在async setup场景下 - 不要在
onTick回调里直接修改 props 或调用异步接口,应通过emit或defineExpose交由父组件决策
搭配组件使用的轻量模式(适合简单场景)
如果只是单次倒计时(如登录页 60 秒重发验证码),可跳过完整 Hook,直接在组件内用 useCountdown(60) 调用,并配合 watchEffect 响应状态变化:
-
watchEffect监听counter,当为 0 时触发发送逻辑或 UI 提示 - 按钮点击时先判断
counter.value === 60,防止重复触发 - 倒计时中禁用按钮,结束时恢复,用
:disabled="counter.value !== 60"即可
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









