当前位置:首页 > VUE

vue实现倒计时组件

2026-02-09 19:21:31VUE

Vue 倒计时组件实现

方法一:基础倒计时(基于 setInterval)

创建 Countdown.vue 文件,使用 setInterval 实现倒计时逻辑:

<template>
  <div>{{ 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 hours = Math.floor(this.remainingTime / 3600)
      const minutes = Math.floor((this.remainingTime % 3600) / 60)
      const seconds = this.remainingTime % 60

      return this.format
        .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.calculateRemainingTime()
      this.timer = setInterval(() => {
        this.calculateRemainingTime()
        if (this.remainingTime <= 0) {
          this.clearTimer()
          this.$emit('end')
        }
      }, 1000)
    },
    calculateRemainingTime() {
      const target = new Date(this.targetTime).getTime()
      const now = Date.now()
      this.remainingTime = Math.max(0, Math.floor((target - now) / 1000))
    },
    clearTimer() {
      if (this.timer) {
        clearInterval(this.timer)
        this.timer = null
      }
    }
  }
}
</script>

方法二:使用 requestAnimationFrame(更高精度)

vue实现倒计时组件

适用于需要更高精度的场景:

<template>
  <div>{{ formattedTime }}</div>
</template>

<script>
export default {
  props: {
    duration: {
      type: Number,
      required: true
    }
  },
  data() {
    return {
      startTime: null,
      remainingTime: this.duration,
      animationFrame: null
    }
  },
  computed: {
    formattedTime() {
      const ms = this.remainingTime
      const seconds = Math.floor(ms / 1000) % 60
      const minutes = Math.floor(ms / (1000 * 60)) % 60
      const hours = Math.floor(ms / (1000 * 60 * 60))

      return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
    }
  },
  mounted() {
    this.startCountdown()
  },
  beforeDestroy() {
    this.stopCountdown()
  },
  methods: {
    startCountdown() {
      this.startTime = performance.now()
      this.animationFrame = requestAnimationFrame(this.updateCountdown)
    },
    updateCountdown(timestamp) {
      const elapsed = timestamp - this.startTime
      this.remainingTime = Math.max(0, this.duration - elapsed)

      if (this.remainingTime > 0) {
        this.animationFrame = requestAnimationFrame(this.updateCountdown)
      } else {
        this.$emit('end')
      }
    },
    stopCountdown() {
      if (this.animationFrame) {
        cancelAnimationFrame(this.animationFrame)
      }
    }
  }
}
</script>

方法三:带暂停/继续功能的倒计时

vue实现倒计时组件

扩展基础版本,增加控制功能:

<template>
  <div>
    <div>{{ formattedTime }}</div>
    <button @click="toggle">{{ isRunning ? '暂停' : '继续' }}</button>
  </div>
</template>

<script>
export default {
  props: {
    seconds: {
      type: Number,
      default: 60
    }
  },
  data() {
    return {
      remainingTime: this.seconds,
      isRunning: false,
      timer: null,
      lastUpdate: null
    }
  },
  computed: {
    formattedTime() {
      const minutes = Math.floor(this.remainingTime / 60)
      const seconds = this.remainingTime % 60
      return `${minutes}:${seconds.toString().padStart(2, '0')}`
    }
  },
  mounted() {
    this.start()
  },
  beforeDestroy() {
    this.stop()
  },
  methods: {
    start() {
      this.isRunning = true
      this.lastUpdate = Date.now()
      this.timer = setInterval(() => {
        const now = Date.now()
        const diff = Math.floor((now - this.lastUpdate) / 1000)
        this.lastUpdate = now

        this.remainingTime = Math.max(0, this.remainingTime - diff)
        if (this.remainingTime <= 0) {
          this.stop()
          this.$emit('end')
        }
      }, 1000)
    },
    stop() {
      this.isRunning = false
      clearInterval(this.timer)
    },
    toggle() {
      if (this.isRunning) {
        this.stop()
      } else {
        this.start()
      }
    }
  }
}
</script>

优化建议

  1. 使用 Web Worker 处理长时间倒计时,避免主线程阻塞
  2. 添加时区处理,确保目标时间计算准确
  3. 实现格式化函数支持更多自定义格式
  4. 添加多语言支持
  5. 使用 CSS 动画增强视觉效果

组件使用示例

<template>
  <Countdown 
    :target-time="targetDate" 
    format="HH:mm:ss"
    @end="handleCountdownEnd"
  />
</template>

<script>
import Countdown from './Countdown.vue'

export default {
  components: { Countdown },
  data() {
    return {
      targetDate: new Date(Date.now() + 3600 * 1000) // 1小时后
    }
  },
  methods: {
    handleCountdownEnd() {
      console.log('倒计时结束')
    }
  }
}
</script>

标签: 倒计时组件
分享给朋友:

相关文章

uniapp组件写法

uniapp组件写法

Uniapp 组件的基本写法 Uniapp 的组件写法与 Vue 类似,支持单文件组件(.vue 文件)。一个基本的组件通常包含三个部分:<template>、<script>…

vue轮播组件实现

vue轮播组件实现

vue轮播组件实现方法 使用第三方库(如Swiper) 安装Swiper库: npm install swiper 在Vue组件中引入: <template> <div cl…

vue radio组件实现

vue radio组件实现

Vue Radio 组件实现 在 Vue 中实现 Radio 组件可以通过原生 HTML 的 <input type="radio"> 结合 Vue 的响应式特性来完成。以下是几种常见的实…

vue动态组件实现

vue动态组件实现

动态组件的基本用法 在Vue中,动态组件通过<component>标签和is属性实现。is属性可以绑定组件名称或组件选项对象,实现动态切换。 <template> <…

vue表格组件实现

vue表格组件实现

Vue表格组件实现 基础表格实现 使用el-table组件实现基础表格功能。安装Element UI后,引入el-table和el-table-column组件。 <template>…

vue 实现toast组件

vue 实现toast组件

实现 Vue Toast 组件的方法 创建基础 Toast 组件 在 Vue 项目中创建一个基础 Toast 组件,通常包含消息内容和显示控制逻辑。 <template> <d…