参考:vant-contrib.gitee.io/vant/#/zh-C…
开发中需要用到倒计时功能,苦于没有引入vant ui库,于是动手写了一个。
介绍
提供倒计时管理能力。
代码演示
基本用法
<span>总时间:{{ current.total }}</span>
<span>剩余天数:{{ current.days }}</span>
<span>剩余小时:{{ current.hours }}</span>
<span>剩余分钟:{{ current.minutes }}</span>
<span>剩余秒数:{{ current.seconds }}</span>
<span>剩余毫秒:{{ current.milliseconds }}</span>
<script lang='ts' setup>
import { toRefs } from 'vue'
import { useCountDown } from '../../hook/use'
const countDown = useCountDown({
// 倒计时 24 小时
time: 24 * 60 * 60 * 1000,
autoStart: true
})
const { current } = toRefs(countDown)
</script>
毫秒级渲染
<script lang='ts' setup>
import { toRefs } from 'vue'
import { useCountDown } from '../../hook/use'
const countDown = useCountDown({
// 倒计时 24 小时
time: 24 * 60 * 60 * 1000,
millisecond: true,
autoStart: true
})
const { current } = toRefs(countDown)
</script>
API
type CurrentTime = {
total: number
days: string
hours: string
minutes: string
seconds: string
milliseconds: string
};
type CountDown = {
start: () => void
pause: () => void
reset: (totalTime: number, autoStart?: boolean) => void
current: CurrentTime
};
type UseCountDownOptions = {
time: number
autoStart?: boolean
millisecond?: boolean
onChange?: (current: CurrentTime) => void
onFinish?: () => void
};
function useCountDown(options: UseCountDownOptions): CountDown;
源码
import { reactive } from 'vue'
interface CurrentTime {
total: number
days: string
hours: string
minutes: string
seconds: string
milliseconds: string
}
interface CountDown {
start: () => void
pause: () => void
reset: (totalTime: number, autoStart?: boolean) => void
current: CurrentTime
}
interface UseCountDownOptions {
time: number
autoStart?: boolean
millisecond?: boolean
onChange?: (current: CurrentTime) => void
onFinish?: () => void
}
export const useCountDown = (options: UseCountDownOptions): CountDown => {
let countdownTime: NodeJS.Timeout
const diff = options.millisecond ? 4 : 1000
const current = reactive({
total: 0,
days: '00',
hours: '00',
minutes: '00',
seconds: '00',
milliseconds: '00',
})
const timeDataFormat = () => {
if (current.total >= 0) {
current.days = Math.floor(current.total / (24 * 60 * 60 * 1000))
.toString()
.padStart(2, '0')
current.hours = Math.floor((current.total % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000))
.toString()
.padStart(2, '0')
current.minutes = Math.floor((current.total % (60 * 60 * 1000)) / (60 * 1000))
.toString()
.padStart(2, '0')
current.seconds = Math.floor((current.total % 60000) / 1000)
.toString()
.padStart(2, '0')
current.milliseconds = Math.floor(current.total % 1000)
.toString()
.padStart(2, '0')
}
}
const start = () => {
clearTimeout(countdownTime)
current.total = current.total - diff
if (current.total >= 0) {
timeDataFormat()
options.onChange?.(current)
countdownTime = setTimeout(() => {
start()
}, diff)
} else {
options.onFinish?.()
}
}
const pause = () => {
clearTimeout(countdownTime)
}
const reset = (totalTime: number, autoStart = false) => {
clearTimeout(countdownTime)
current.total = totalTime
timeDataFormat()
if (autoStart) {
start()
}
}
reset(options.time, options.autoStart)
return {
start,
pause,
reset,
current,
}
}