Skip to content

Countdown 倒计时

基于 Vue 3 的高性能倒计时组件,使用全局共享定时器实现,所有组件实例共用一个定时器,节省性能开销。

基本用法

vue
<template>
  <div>
    <!-- 基本倒计时(使用秒数) -->
    <g-countdown :target="60"></g-countdown>

    <!-- 使用目标时间戳 -->
    <g-countdown :target="targetTimestamp"></g-countdown>

    <!-- 自定义格式 -->
    <g-countdown :target="120" format="{minutes}:{seconds}"></g-countdown>

    <!-- 手动控制 -->
    <div>
      <g-countdown ref="countdownRef" :target="300" :auto-start="false"></g-countdown>
      <el-button @click="handleStart">开始</el-button>
      <el-button @click="handlePause">暂停</el-button>
      <el-button @click="handleReset">重置</el-button>
    </div>

    <!-- 自定义内容 -->
    <g-countdown :target="86400">
      <template v-slot="{ days, hours, minutes, seconds }">
        <span class="time-item">{{ days }}</span
        >天 <span class="time-item">{{ hours }}</span
        >时 <span class="time-item">{{ minutes }}</span
        >分 <span class="time-item">{{ seconds }}</span
        >秒
      </template>
    </g-countdown>
  </div>
</template>

<script setup>
import { ref } from 'vue'

// 目标时间戳(明天这个时候)
const targetTimestamp = ref(Date.now() + 24 * 60 * 60 * 1000)

// 手动控制的倒计时
const countdownRef = ref(null)
const handleStart = () => countdownRef.value?.start()
const handlePause = () => countdownRef.value?.pause()
const handleReset = () => countdownRef.value?.reset()
</script>

<style scoped>
.time-item {
  background-color: #409eff;
  color: white;
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: bold;
}
</style>

属性说明

属性名说明类型默认值
target目标时间戳(毫秒)或倒计时秒数Number/String必填
autoStart是否自动开始倒计时Booleantrue
stopOnZero是否在倒计时结束后停止Booleantrue
customClass自定义类名String/Array/Object''
format格式化模板,支持 {days}, {hours}, {minutes}, {seconds} 占位符String'{days}天{hours}小时{minutes}分{seconds}秒'
leadingZero是否显示前导零Booleantrue

事件

事件名说明回调参数
finish倒计时结束时触发-
tick每秒更新时触发{days, hours, minutes, seconds, total}
update:target更新目标时间时触发target

插槽

插槽名说明作用域参数
default自定义倒计时显示内容{ days, hours, minutes, seconds }

方法

方法名说明参数
start开始倒计时-
pause暂停倒计时-
reset重置倒计时-

组件实例属性

属性名说明类型
remainingTime当前剩余时间(秒)Number

全局定时器管理器

组件内部使用了全局定时器管理器 timerManager,确保所有 Countdown 组件实例共享同一个定时器,有效减少浏览器性能消耗。主要功能包括:

  • 自动管理定时器的创建和销毁
  • 当所有倒计时组件都被销毁时,自动清除定时器
  • 通过发布-订阅模式通知所有组件更新
  • 错误捕获,防止单个组件错误影响整个定时器

高级用法

动态更新目标时间

vue
<template>
  <div>
    <g-countdown v-model:target="targetTime"></g-countdown>
    <el-button @click="updateTarget">更新目标时间</el-button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const targetTime = ref(60)
const updateTarget = () => {
  targetTime.value = 120 // 更新为120秒
}
</script>

监听倒计时状态

vue
<template>
  <g-countdown :target="targetTime" @finish="handleFinish" @tick="handleTick"></g-countdown>
</template>

<script setup>
import { ref } from 'vue'

const targetTime = ref(10)
const handleFinish = () => {
  console.log('倒计时结束!')
  // 可以在这里执行一些操作,如显示提示、触发新流程等
}

const handleTick = (timeInfo) => {
  console.log('当前倒计时状态:', timeInfo)
  // timeInfo = { days, hours, minutes, seconds, total }
}
</script>

自定义样式

vue
<template>
  <g-countdown :target="86400" class="custom-countdown"></g-countdown>
</template>

<style scoped>
.custom-countdown {
  font-size: 20px;
  font-weight: bold;
  color: #409eff;

  /* 可以通过CSS选择器定位不同部分 */
  &:deep(.g-countdown) {
    letter-spacing: 2px;
  }
}
</style>

注意事项

  1. 性能优化:组件使用全局定时器共享机制,适合在页面中使用多个倒计时组件的场景
  2. 时间精度:倒计时基于JavaScript定时器实现,精度可能受到浏览器性能影响
  3. 目标时间判断:组件会自动判断传入的target值是时间戳还是秒数(大于2001年时间戳阈值的被视为时间戳)
  4. 组件销毁:组件会在卸载时自动清理定时器订阅,无需手动处理

样式定制

组件默认样式简洁,可以通过 customClass 属性或直接在父组件中使用深度选择器进行样式定制。