倒计时功能实现
功能
纯前端实现倒计时功能,传入一个将来某一刻时间点,页面显示剩余 xx 时 xx 分 xx 秒(也可以拓展到年月日),并不断递减.element-plus已经有这个功能了源码,我们看一下这个功能的实现.
实现思路
抽离成单独的组件,组件的props
包含value
属性,表示倒计时的截止时间点.
因为要实时更新所以我们使用了 requestAnimationFrame 这个函数.剩余时间为props.value
与当前时间的差值(Date.now())
.
这里拿到的剩余时间为时间戳,所以还要一个辅助函数来格式化,将其转化为xx 时 xx 分 xx 秒
类似格式.
在使用组件的时候,要实现暂停和继续功能,可以通过暴露出去的 displayValue
属性来实现.
<script setup>
import { ref, onMounted, computed ,watch} from 'vue'
const props = defineProps({
value: { type: Number, default: 0 }
})
const rawValue = ref(0)
let timer
const startTimer = () => {
let diff = props.value - Date.now()
if (diff <= 0) {
diff = 0
stopTimer()
} else {
timer = requestAnimationFrame(startTimer)
}
rawValue.value = diff
}
const stopTimer = () => {
if (timer) {
cancelAnimationFrame(timer)
timer = null
}
}
const timeUnits = [
['H', 1000 * 60 * 60], // hours
['m', 1000 * 60], // minutes
['s', 1000], // seconds
['S', 1], // million seconds
]
const formatTimer = (timestamp) => {
const value = timeUnits.map(([name, uit]) => {
const uitValue = Math.floor(timestamp / uit)
timestamp -= uitValue * uit
return `${uitValue}${name}`
})
return value.join('')
}
const displayValue = computed(() =>
formatTimer(rawValue.value)
)
watch(
() => props.value,
() => {
stopTimer()
startTimer()
}
)
onMounted(() => {
startTimer()
})
defineExpose({
rawValue
})
</script>
<template>
<div>
{{ displayValue }}
</div>
</template>