更新:登录功能
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import { ref, computed, onBeforeUnmount } from 'vue'
|
||||
import { isDef } from '../common/util'
|
||||
import { useRaf } from './useRaf'
|
||||
|
||||
// 定义倒计时时间的数据结构
|
||||
export type CurrentTime = {
|
||||
days: number
|
||||
hours: number
|
||||
total: number
|
||||
minutes: number
|
||||
seconds: number
|
||||
milliseconds: number
|
||||
}
|
||||
|
||||
// 定义倒计时的配置项
|
||||
export type UseCountDownOptions = {
|
||||
time: number // 倒计时总时间,单位为毫秒
|
||||
millisecond?: boolean // 是否开启毫秒级倒计时,默认为 false
|
||||
onChange?: (current: CurrentTime) => void // 倒计时每次变化时的回调函数
|
||||
onFinish?: () => void // 倒计时结束时的回调函数
|
||||
}
|
||||
|
||||
// 定义常量
|
||||
const SECOND = 1000
|
||||
const MINUTE = 60 * SECOND
|
||||
const HOUR = 60 * MINUTE
|
||||
const DAY = 24 * HOUR
|
||||
|
||||
// 将时间转换为倒计时数据结构
|
||||
function parseTime(time: number): CurrentTime {
|
||||
const days = Math.floor(time / DAY)
|
||||
const hours = Math.floor((time % DAY) / HOUR)
|
||||
const minutes = Math.floor((time % HOUR) / MINUTE)
|
||||
const seconds = Math.floor((time % MINUTE) / SECOND)
|
||||
const milliseconds = Math.floor(time % SECOND)
|
||||
|
||||
return {
|
||||
total: time,
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds,
|
||||
milliseconds
|
||||
}
|
||||
}
|
||||
|
||||
// 判断两个时间是否在同一秒内
|
||||
function isSameSecond(time1: number, time2: number): boolean {
|
||||
return Math.floor(time1 / 1000) === Math.floor(time2 / 1000)
|
||||
}
|
||||
|
||||
// 定义 useCountDown 函数
|
||||
export function useCountDown(options: UseCountDownOptions) {
|
||||
let endTime: number // 结束时间
|
||||
let counting: boolean // 是否计时中
|
||||
|
||||
const { start: startRaf, cancel: cancelRaf } = useRaf(tick)
|
||||
|
||||
const remain = ref(options.time) // 剩余时间
|
||||
const current = computed(() => parseTime(remain.value)) // 当前倒计时数据
|
||||
|
||||
// 暂停倒计时
|
||||
const pause = () => {
|
||||
counting = false
|
||||
cancelRaf()
|
||||
}
|
||||
|
||||
// 获取当前剩余时间
|
||||
const getCurrentRemain = () => Math.max(endTime - Date.now(), 0)
|
||||
|
||||
// 设置剩余时间
|
||||
const setRemain = (value: number) => {
|
||||
remain.value = value
|
||||
isDef(options.onChange) && options.onChange(current.value)
|
||||
if (value === 0) {
|
||||
pause()
|
||||
isDef(options.onFinish) && options.onFinish()
|
||||
}
|
||||
}
|
||||
|
||||
// 每毫秒更新一次倒计时
|
||||
const microTick = () => {
|
||||
if (counting) {
|
||||
setRemain(getCurrentRemain())
|
||||
if (remain.value > 0) {
|
||||
startRaf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 每秒更新一次倒计时
|
||||
const macroTick = () => {
|
||||
if (counting) {
|
||||
const remainRemain = getCurrentRemain()
|
||||
if (!isSameSecond(remainRemain, remain.value) || remainRemain === 0) {
|
||||
setRemain(remainRemain)
|
||||
}
|
||||
|
||||
if (remain.value > 0) {
|
||||
startRaf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据配置项选择更新方式
|
||||
function tick() {
|
||||
if (options.millisecond) {
|
||||
microTick()
|
||||
} else {
|
||||
macroTick()
|
||||
}
|
||||
}
|
||||
|
||||
// 开始倒计时
|
||||
const start = () => {
|
||||
if (!counting) {
|
||||
endTime = Date.now() + remain.value
|
||||
counting = true
|
||||
startRaf()
|
||||
}
|
||||
}
|
||||
|
||||
// 重置倒计时
|
||||
const reset = (totalTime: number = options.time) => {
|
||||
pause()
|
||||
remain.value = totalTime
|
||||
}
|
||||
|
||||
// 在组件卸载前暂停倒计时
|
||||
onBeforeUnmount(pause)
|
||||
|
||||
return {
|
||||
start,
|
||||
pause,
|
||||
reset,
|
||||
current
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user