当前位置:首页 > 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>

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

相关文章

Vue组件实现方法

Vue组件实现方法

Vue组件的基本实现 Vue组件是Vue.js的核心概念之一,允许将UI拆分为独立可复用的代码片段。组件的实现方式有多种,以下是常见的几种方法。 单文件组件(SFC) 单文件组件以.vue为后缀,将…

如何判断react组件

如何判断react组件

判断 React 组件的依据 React 组件的判断通常基于其定义方式、功能特性和代码结构。以下是几种常见的判断方法: 函数组件与类组件 函数组件是通过 JavaScript 函数定义的,接收 pr…

react如何删除组件

react如何删除组件

删除 React 组件的几种方法 条件渲染法 通过状态控制组件是否渲染。当状态为 false 时,组件会被移除: const [showComponent, setShowComponent…

vue实现组件切换

vue实现组件切换

Vue 组件切换的实现方法 在 Vue 中实现组件切换有多种方式,以下是几种常见的方法: 动态组件 使用 Vue 内置的 <component> 元素和 is 属性可以动态切换组件:…

vue实现组件刷新

vue实现组件刷新

强制重新渲染组件 使用 this.$forceUpdate() 方法可以强制 Vue 实例重新渲染,但不会更新子组件。适用于依赖非响应式数据的情况。 methods: { refreshComp…

vue 实现通用组件

vue 实现通用组件

Vue 实现通用组件的方法 封装可复用的组件 将通用功能抽象为独立组件,通过props接收外部数据,通过events与父组件通信。例如封装按钮、输入框、弹窗等基础组件。 使用插槽增强灵活性 通过默认…