vue实现倒计时组件
Vue 倒计时组件实现
功能需求分析
- 显示剩余时间(天、时、分、秒)
- 支持自定义时间格式
- 支持暂停/继续
- 结束时触发回调事件
基础实现方案
创建 CountDown.vue 组件文件:

<template>
<div class="countdown">
{{ formattedTime }}
</div>
</template>
<script>
export default {
props: {
targetTime: {
type: [Date, Number, String],
required: true
},
format: {
type: String,
default: 'HH:mm:ss'
}
},
data() {
return {
remainingTime: 0,
timer: null
}
},
computed: {
formattedTime() {
const days = Math.floor(this.remainingTime / (1000 * 60 * 60 * 24))
const hours = Math.floor((this.remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
const minutes = Math.floor((this.remainingTime % (1000 * 60 * 60)) / (1000 * 60))
const seconds = Math.floor((this.remainingTime % (1000 * 60)) / 1000)
return this.format
.replace('DD', days.toString().padStart(2, '0'))
.replace('HH', hours.toString().padStart(2, '0'))
.replace('mm', minutes.toString().padStart(2, '0'))
.replace('ss', seconds.toString().padStart(2, '0'))
}
},
mounted() {
this.startCountdown()
},
beforeDestroy() {
this.clearTimer()
},
methods: {
startCountdown() {
this.clearTimer()
this.updateRemainingTime()
this.timer = setInterval(() => {
this.updateRemainingTime()
}, 1000)
},
updateRemainingTime() {
const now = new Date().getTime()
const target = new Date(this.targetTime).getTime()
this.remainingTime = target - now
if (this.remainingTime <= 0) {
this.remainingTime = 0
this.clearTimer()
this.$emit('finish')
}
},
clearTimer() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
pause() {
this.clearTimer()
},
resume() {
this.startCountdown()
}
}
}
</script>
使用方法
<template>
<CountDown
:target-time="targetDate"
format="DD天 HH:mm:ss"
@finish="handleFinish"
/>
</template>
<script>
import CountDown from './CountDown.vue'
export default {
components: { CountDown },
data() {
return {
targetDate: new Date(Date.now() + 86400000) // 24小时后
}
},
methods: {
handleFinish() {
console.log('倒计时结束')
}
}
}
</script>
高级功能扩展

- 毫秒级精度
// 修改定时器间隔 this.timer = setInterval(() => { this.updateRemainingTime() }, 100)
// 修改格式显示 const milliseconds = Math.floor(this.remainingTime % 1000) format.replace('SSS', milliseconds.toString().padStart(3, '0'))
2. 自定义渲染
```vue
<template>
<div class="countdown">
<slot :time="timeData">
{{ formattedTime }}
</slot>
</div>
</template>
// 添加计算属性
timeData() {
return {
days: Math.floor(this.remainingTime / (1000 * 60 * 60 * 24)),
hours: Math.floor((this.remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
minutes: Math.floor((this.remainingTime % (1000 * 60 * 60)) / (1000 * 60)),
seconds: Math.floor((this.remainingTime % (1000 * 60)) / 1000),
milliseconds: Math.floor(this.remainingTime % 1000),
total: this.remainingTime
}
}
- 服务端时间同步
async fetchServerTime() { const response = await fetch('/api/time') const { serverTime } = await response.json() this.serverTimeOffset = new Date().getTime() - new Date(serverTime).getTime() },
updateRemainingTime() { const now = new Date().getTime() - this.serverTimeOffset // 其余逻辑不变 }
注意事项
- 组件销毁时务必清除定时器
- 处理时区问题时可统一使用UTC时间
- 性能优化:高精度倒计时使用requestAnimationFrame替代setInterval
- 移动端注意页面隐藏时的定时器处理






