Vue倒计时组件通过状态闸门(isFinished)确保finish事件仅触发一次,配合watch重置状态、onUnmounted清理定时器,实现精准、可重用、无内存泄漏的事件广播。

Vue 自定义事件处理倒计时结束的事件广播,核心是用 $emit 主动触发、$on(或 @事件名)监听,不依赖全局总线也能干净解耦。关键不在“怎么发”,而在“什么时候发一次、怎么确保不重复、父组件怎么接住”。
倒计时结束时精准触发一次 finish 事件
不能在定时器回调里无条件 this.$emit('finish')——每秒都触发,父组件会收到几十次。必须加状态闸门:
- 用一个
ref(Vue 3)或data字段(Vue 2)标记是否已结束,比如isFinished = false - 倒计时归零瞬间,先判断
if (!isFinished) { isFinished = true; this.$emit('finish') } - 后续秒数为负或继续递减时,跳过 emit
父组件用 v-on 直接监听,无需 eventHub
倒计时组件是子组件,父组件通过模板绑定即可接收,最简洁自然:
- 模板中:
- 父组件 methods 里写:
handleFinish() { console.log('倒计时到底了'); this.showAlert = true; } - 不需要创建空 Vue 实例、不用
this.$root.eventHub,避免全局污染和内存泄漏风险
目标时间变更时重置事件状态
如果父组件动态改了 target-time,倒计时要重新开始,finish 事件也应可再次触发:
- 用
watch监听targetTime变化 - 变化时把
isFinished设为false,并清掉旧定时器、启动新倒计时 - 这样下次归零又能正常 emit,不会被上次的闸门锁死
定时器清理要闭环,防止内存泄漏
组件卸载时,必须清除 setTimeout 或 setInterval,否则事件可能还在后台执行并尝试 emit:
- Vue 3:
onUnmounted(() => clearTimeout(timerRef.value)) - Vue 2:
beforeDestroy() { clearInterval(this.timer); } - 尤其用递归
setTimeout对齐整秒时,timer 引用必须可访问、可清除
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











