vue实现活动倒计时
实现活动倒计时的基本思路
在Vue中实现活动倒计时通常需要获取目标时间与当前时间的差值,通过定时器动态更新剩余时间。核心逻辑包括计算时间差、格式化和动态渲染。

使用计算属性与定时器
定义一个目标时间(如活动结束时间),通过setInterval每秒更新当前时间并计算剩余时间。将剩余时间分解为天、小时、分钟和秒。

<template>
<div>
<p>距离活动结束还剩: {{ days }}天 {{ hours }}小时 {{ minutes }}分钟 {{ seconds }}秒</p>
</div>
</template>
<script>
export default {
data() {
return {
targetTime: new Date('2023-12-31 23:59:59').getTime(),
currentTime: new Date().getTime(),
timer: null
}
},
computed: {
timeDiff() {
return this.targetTime - this.currentTime;
},
days() {
return Math.floor(this.timeDiff / (1000 * 60 * 60 * 24));
},
hours() {
return Math.floor((this.timeDiff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
},
minutes() {
return Math.floor((this.timeDiff % (1000 * 60 * 60)) / (1000 * 60));
},
seconds() {
return Math.floor((this.timeDiff % (1000 * 60)) / 1000);
}
},
mounted() {
this.timer = setInterval(() => {
this.currentTime = new Date().getTime();
if (this.timeDiff <= 0) {
clearInterval(this.timer);
}
}, 1000);
},
beforeDestroy() {
clearInterval(this.timer);
}
}
</script>
使用第三方库优化
对于复杂场景(如跨时区、格式化),可以使用moment.js或day.js库简化日期操作。
import dayjs from 'dayjs';
export default {
data() {
return {
targetTime: dayjs('2023-12-31 23:59:59'),
now: dayjs(),
timer: null
}
},
computed: {
countdown() {
const diff = this.targetTime.diff(this.now, 'second');
return {
days: Math.floor(diff / 86400),
hours: Math.floor((diff % 86400) / 3600),
minutes: Math.floor((diff % 3600) / 60),
seconds: diff % 60
};
}
},
mounted() {
this.timer = setInterval(() => {
this.now = dayjs();
if (this.targetTime.diff(this.now, 'second') <= 0) {
clearInterval(this.timer);
}
}, 1000);
}
}
封装为可复用组件
将倒计时逻辑封装为组件,通过props接收目标时间,通过emit触发结束事件。
<template>
<div>
<slot :countdown="countdown">
{{ countdown.days }}天 {{ countdown.hours }}小时 {{ countdown.minutes }}分钟 {{ countdown.seconds }}秒
</slot>
</div>
</template>
<script>
export default {
props: {
endTime: {
type: [String, Date, Number],
required: true
}
},
data() {
return {
now: new Date().getTime()
};
},
computed: {
targetTime() {
return new Date(this.endTime).getTime();
},
countdown() {
const diff = this.targetTime - this.now;
return {
days: Math.floor(diff / (1000 * 60 * 60 * 24)),
hours: Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
minutes: Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)),
seconds: Math.floor((diff % (1000 * 60)) / 1000)
};
}
},
mounted() {
const timer = setInterval(() => {
this.now = new Date().getTime();
if (this.targetTime - this.now <= 0) {
clearInterval(timer);
this.$emit('end');
}
}, 1000);
this.$once('hook:beforeDestroy', () => clearInterval(timer));
}
};
</script>
注意事项
- 性能优化:在组件销毁时清除定时器,避免内存泄漏。
- 时区处理:确保目标时间与用户本地时区一致,必要时使用
UTC时间。 - 格式化:可通过
padStart补零显示(如seconds.toString().padStart(2, '0'))。 - 服务端渲染:在SSR场景下需兼容
window对象缺失的情况。






