效果
<view class="issue-price-countdown">
?? ??? ??<CountDown :endTimestamp="1745996085000"></CountDown>
?</view>
引入組件
import CountDown from '@/components/CountDown.vue';
<template>
?? ?<view class="countdown">
?? ??? ?<view class="time-box hour">{{ currentHours }}</view>
?? ??? ?<text class="colon">:</text>
?? ??? ?<view class="time-box minute">{{ currentMinutes }}</view>
?? ??? ?<text class="colon">:</text>
?? ??? ?<view class="time-box second">{{ currentSeconds }}</view>
?? ?</view>
</template>
<script>
?? ?export default {
?? ??? ?props: {
?? ??? ??? ?// 接收13位時間戳(結束時間)
?? ??? ??? ?endTimestamp: {
?? ??? ??? ??? ?type: Number,
?? ??? ??? ??? ?required: true
?? ??? ??? ?}
?? ??? ?},
?? ??? ?data() {
?? ??? ??? ?return {
?? ??? ??? ??? ?remainingTime: 0, ?// 剩余總秒數
?? ??? ??? ??? ?timer: null,
?? ??? ??? ??? ?currentHours: 0,
?? ??? ??? ??? ?currentMinutes: 0,
?? ??? ??? ??? ?currentSeconds: 0
?? ??? ??? ?}
?? ??? ?},
?? ??? ?methods: {
?? ??? ? ?// 初始化倒計時
?? ??? ??? ?initCountdown() {
?? ??? ??? ??? ?this.clearTimer()
?? ??? ??? ??? ?this.calculateRemaining()
?? ??? ??? ??? ?
?? ??? ??? ??? ?if (this.remainingTime > 0) {
?? ??? ??? ??? ??? ?this.timer = setInterval(() => {
?? ??? ??? ??? ??? ??? ?this.updateTime()
?? ??? ??? ??? ??? ?}, 1000)
?? ??? ??? ??? ?}
?? ??? ??? ?},
?? ??? ??? ?// 計算剩余時間
?? ??? ??? ?calculateRemaining() {
?? ??? ??? ??? ?const now = Date.now()
?? ??? ??? ??? ?this.remainingTime = Math.max(0, Math.floor((this.endTimestamp - now) / 1000))
?? ??? ??? ??? ?this.updateDisplayTime()
?? ??? ??? ?},
?? ??? ??? ?
?? ??? ??? ?// 更新時間顯示
?? ??? ??? ?updateDisplayTime() {
?? ??? ??? ??? ?let seconds = this.remainingTime % 60
?? ??? ??? ??? ?let minutes = Math.floor(this.remainingTime / 60) % 60
?? ??? ??? ??? ?const hours = Math.floor(this.remainingTime / 3600)
?? ?
?? ??? ??? ??? ?// 實現級聯更新效果
?? ??? ??? ??? ?if (this.currentSeconds === 0 && seconds === 59) {
?? ??? ??? ??? ??? ?this.currentMinutes = minutes
?? ??? ??? ??? ?}
?? ??? ??? ??? ?if (this.currentMinutes === 0 && minutes === 59) {
?? ??? ??? ??? ??? ?this.currentHours = hours
?? ??? ??? ??? ?}
?? ?
?? ??? ??? ??? ?this.currentSeconds = this.pad(seconds)
?? ??? ??? ??? ?this.currentMinutes = this.pad(minutes)
?? ??? ??? ??? ?this.currentHours = this.pad(hours)
?? ??? ??? ?},
?? ??? ??? ?// 每秒更新
?? ??? ??? ?updateTime() {
?? ??? ??? ??? ?this.remainingTime = Math.max(0, this.remainingTime - 1)
?? ??? ??? ??? ?this.updateDisplayTime()
?? ?
?? ??? ??? ??? ?if (this.remainingTime <= 0) {
?? ??? ??? ??? ??? ?this.clearTimer()
?? ??? ??? ??? ??? ?this.$emit('timeup')
?? ??? ??? ??? ?}
?? ??? ??? ?},
?? ??? ??? ?
?? ??? ??? ?// 補零函數
?? ??? ??? ?pad(n) {
?? ??? ??? ??? ?return n < 10 ? '0' + n : n
?? ??? ??? ?},
?? ??? ??? ?
?? ??? ??? ?// 清除定時器
?? ??? ??? ?clearTimer() {
?? ??? ??? ??? ?if (this.timer) {
?? ??? ??? ??? ??? ?clearInterval(this.timer)
?? ??? ??? ??? ??? ?this.timer = null
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?},
?? ??? ?watch: {
?? ??? ??? ?endTimestamp: {
?? ??? ??? ??? ?immediate: true,
?? ??? ??? ??? ?handler(newVal) {
?? ??? ??? ??? ??? ?this.initCountdown()
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?},
?? ??? ?created() {
? ? ? ? ??
?? ??? ?}
?? ?}
</script>
<style lang="scss" scoped>
?? ?.countdown {
?? ??? ?display: flex;
?? ??? ?align-items: center;
?? ??? ?justify-content: space-between;
?? ??? ?.time-box {
?? ??? ??? ?width: 52rpx;
?? ??? ??? ?height: 52rpx;
?? ??? ??? ?background: #313131;
?? ??? ??? ?line-height: 52rpx;
?? ??? ??? ?text-align: center;
?? ??? ??? ?border-radius: 10rpx 10rpx 10rpx 10rpx;
?? ??? ??? ?font-weight: bold;
?? ??? ?}
?? ??? ?.colon {
?? ??? ??? ?color: #313131;
?? ??? ??? ?margin: 0 12rpx;
?? ??? ?}
?? ?}
</style>