效果图
代码块
useCountdown.ts
import {onUnmounted, reactive, ref, watch} from "vue";type union = 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds'export type Remains = Record<union, number>;/*** 创建一个倒计时** 用法*/
export const useCountDown = () => {const remainMilliseconds = ref();const started = ref(false);const finished = ref<boolean>();const remains = reactive<Remains>({days: 0,hours: 0,minutes: 0,seconds: 0,milliseconds: 0,});const start = (deadline: number) => {if (started.value) {return}started.value = trueloop(deadline)}const loop = (deadline: number) => {if (typeof requestAnimationFrame == 'function') {if (started.value) {requestAnimationFrame(() => {const nowTime = new Date().getTime();remainMilliseconds.value = deadline - nowTime;finished.value = remainMilliseconds.value <= 0if (finished.value) {stop()}loop(deadline)})}} else {// 降级使用定时器const interval = setInterval(() => {const nowTime = new Date().getTime();remainMilliseconds.value = deadline - nowTime;finished.value = remainMilliseconds.value <= 0if (finished.value) {stop()clearInterval(interval)}}, 16);}}const stop = () => {started.value = false}watch(remainMilliseconds, (value) => {remains.days = Math.max((value / 1000 / 60 / 60 / 24 | 0), 0)remains.hours = Math.max((value / 1000 / 60 / 60 % 24 | 0), 0)remains.minutes = Math.max((value / 1000 / 60 % 60 | 0), 0)remains.seconds = Math.max((value / 1000 % 60 | 0), 0)remains.milliseconds = Math.max((value % 1000 | 0), 0)})onUnmounted(stop)return {finished, remains, start, stop}
}
vue
<template>{{remains.days}}天{{remains.hours}}时{{remains.minutes}}分钟{{remains.seconds}}秒
</template><script setup lang="ts">import { watch } from 'vue';
import { useCountDown } from './useCountDown';const { remains,finished, start } = useCountDown()start(new Date().getTime() + 10 * 10000000)watch(finished,(n:boolean)=>{if(n){alert('done')}})
</script><style lang="scss">
</style>