watchEffect 通过自动追踪 countdown 变化来启停倒计时,配合模块级 timer 变量实现定时器清理与重启,组件卸载时需手动清除避免内存泄漏。

watchEffect 本身不直接控制倒计时,但它能自动追踪响应式数据变化,并在依赖更新时重新执行——这正好适合监听“是否可点击”状态、触发或清理倒计时逻辑。
用 ref 控制倒计时状态和剩余秒数
定义两个响应式变量:countdown 存剩余秒数,isDisabled 表示按钮是否禁用(通常与 countdown > 0 同步):
const countdown = ref(0); const isDisabled = computed(() => countdown.value > 0);
在 watchEffect 中启动/清除定时器
当用户点击发送验证码时,把 countdown 设为 60;watchEffect 会立即检测到变化,启动倒计时。关键点在于:每次重新运行时,先清除上一次的定时器(避免重复叠加),再根据当前值决定是否继续倒数:
let timer = null;
watchEffect(() => {
if (countdown.value <= 0) {
if (timer) {
clearInterval(timer);
timer = null;
}
return;
}
// 每次进入都先清旧定时器(防多次触发)
if (timer) clearInterval(timer);
timer = setInterval(() => {
countdown.value--;
}, 1000);
});
⚠️ 注意:timer 必须是模块级变量(不能用 ref),否则每次重运行都会丢失引用,导致无法清除。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
立即学习“前端免费学习笔记(深入)”;
点击发送时重置倒计时
按钮点击事件里只需重置数值,watchEffect 自动响应:
const handleSendCode = () => {
// 实际发送请求前可加校验
if (isDisabled.value) return;
// 发送请求...
api.sendCode().then(() => {
countdown.value = 60; // ✅ 触发 watchEffect 重启倒计时
});
};
组件卸载时清理定时器(重要!)
避免内存泄漏,必须在组件 onUnmounted 时手动清除:
onUnmounted(() => {
if (timer) {
clearInterval(timer);
timer = null;
}
});
不复杂但容易忽略。倒计时逻辑由此变得声明式:你只管改 countdown.value,其余交给 watchEffect 和生命周期管理。

















