vue3倒计时组件,增加了时间校对

<template>
    <div class="countdown-box">
        <span>{{ formatTime }}</span>
    </div>
</template>

<script lang="ts" setup>

import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
let formatTime = ref(''); //格式化后的时间

const props = defineProps({
    totalTime: Number, //总时长 -1未开始 0已结束
    interval: { //时间间隔
        type: Number,
        default: 1000
    },
})


watch(() => props.totalTime, (newVal, oldVal) => {
    totalTime = newVal;
    stopCountDown()
    startCountDown()

})


//格式化
/**
 * t: 时间
 * type: 显示类型; 0: :; 1: 小时分钟秒
*/
const secondToTimeStr = (t: number, type: any) => {
    let timeStr1 = '', timeStr2 = '', timeStr3 = '';
    if (type == 0) {
        timeStr1 = ':'; timeStr2 = ':'; timeStr3 = ':';
    }else if (type == 1) {
        timeStr1 = '小时'; timeStr2 = '分'; timeStr3 = '秒'
    };
    
    if (!t) return;
    if (t < 60) return "00" + timeStr2 + ((i = t) < 10 ? "0" + i : i);
    if (t < 3600) return "" + ((a = parseInt(t / 60)) < 10 ? "0" + a : a) + timeStr2 + ((i = t % 60) < 10 ? "0" + i : i);
    if (3600 <= t) {
        var a, i, e = parseInt(t / 3600);
        if (type == 0) {
            return (e < 10 ? "0" + e : e) + timeStr1 + ((a = parseInt(t % 3600 / 60)) < 10 ? "0" + a : a) + timeStr2 + ((i = t % 60) < 10 ? "0" + i : i);
        } else if (type == 1) {
            return (e < 10 ? "0" + e : e) + timeStr1 + ((a = parseInt(t % 3600 / 60)) < 10 ? "0" + a : a) + timeStr2 + ((i = t % 60) < 10 ? "0" + i : i) + timeStr3;
        }
    }
}


//时间间隔
const interval = props.interval;
//总时间
let totalTime = props.totalTime
//用来计次数
let count = 0
//开始倒计时的时间
let firstTimer = new Date().getTime();
let timer: NodeJS.Timeout | null | undefined;

// 倒计时回调
const func = () => {
    count++
    let delaytimer = new Date().getTime() - (interval * count + firstTimer)

    let nextTimer = interval - delaytimer
    if (nextTimer < 0) {
        nextTimer = 0
    }
    totalTime -= interval / 1000;
    console.log(`延迟:${delaytimer}ms, 下一次执行:${nextTimer}ms, 还剩:${totalTime}ms。`)
    formatTime.value = secondToTimeStr(totalTime, 0);
    if (totalTime <= 0) {
        formatTime.value = "已结束";
        clearTimeout(timer)
    } else {
        timer = setTimeout(func, nextTimer)
    }
}




//暂停倒计时
const stopCountDown = () => {
    clearTimeout(timer)
}

//开始倒计时
const startCountDown = () => {
    if (totalTime == 0) {
        formatTime.value = "已结束";
    } else if (totalTime <= -1) {
        formatTime.value = "未开始";
    } else {
        count = 0;
        firstTimer = new Date().getTime();
        timer = setTimeout(func, interval)
    }
}

//在开始和结束前要调接口做校对,获取剩余时长传给totalTime
startCountDown();


//暴漏给父组件的方法
defineExpose({
    stopCountDown,
    startCountDown
})


onBeforeUnmount(() => {
    clearTimeout(timer);
})
</script>
<style lang="less" scoped>
.countDown-box {
    display: flex;
    justify-content: center;
    position: absolute;
    color: white;
    font-size: 18px;
    left: 430px;
    top: 25px;

    span {
        color: rgb(255, 255, 0);
        font-weight: 500;
        font-size: 18px;
        width: 50px;
    }
}
</style>

你可能感兴趣的:(javascript,前端,vue3,js定时器校对)