Время чтения: 2 мин.
Что делает useCooldown?
Функция useCooldown
создает таймер обратного отсчета с двумя ключевыми особенностями:
- Сохранение состояния — продолжает отсчет даже после перезагрузки страницы
- Реактивность — автоматически обновляет интерфейс при изменении времени
Основной функционал
import { useCountdown, useStorage } from '@vueuse/core'
import { onMounted, watch } from 'vue'
export function useCooldown(seconds = 0, storageKey = 'cooldown') {
const cooldownEnd = useStorage(storageKey, 0)
const getRemainingSeconds = () => {
const now = Math.floor(Date.now() / 1000)
return Math.max(0, cooldownEnd.value - now)
}
const { remaining, start: startCountdown } = useCountdown(getRemainingSeconds())
const start = (value = seconds) => {
const now = Math.floor(Date.now() / 1000)
cooldownEnd.value = now + value
startCountdown(value)
}
watch(remaining, (value) => {
const now = Math.floor(Date.now() / 1000)
cooldownEnd.value = now + value
})
onMounted(() => {
const remainingSeconds = getRemainingSeconds()
if (remainingSeconds > 0) {
start(remainingSeconds)
}
})
return { cooldown: remaining, start }
}
Параметры функции
seconds
(по умолчанию 0) — начальное время отсчета в секундахstorageKey
(по умолчанию ‘cooldown’) — ключ для хранения состояния
Возвращаемые значения
cooldown
— реактивное число, оставшееся время в секундахstart
— функция для запуска/перезапуска таймера
Пример использования
Базовый пример
<script setup>
import { useCooldown } from './useCooldown'
const { cooldown, start } = useCooldown(60)
function handleClick() {
if (cooldown > 0) return
console.log('Action performed!')
start() // Запускаем 60-секундный таймер
}
</script>
<template>
<button @click="handleClick" :disabled="cooldown > 0">
{{ cooldown > 0 ? `Доступно через ${cooldown} сек.` : 'Выполнить действие' }}
</button>
</template>
Пример с несколькими таймерами
<script setup>
import { useCooldown } from './useCooldown'
const emailTimer = useCooldown(30, 'email-cooldown')
const smsTimer = useCooldown(60, 'sms-cooldown')
function sendEmail() {
if (emailTimer.cooldown > 0) return
console.log('Email sent')
emailTimer.start()
}
function sendSMS() {
if (smsTimer.cooldown > 0) return
console.log('SMS sent')
smsTimer.start(90) // Переопределяем стандартное значение
}
</script>
Кастомное отображение времени
<script setup>
import { computed } from 'vue'
import { useCooldown } from './useCooldown'
const { cooldown, start } = useCooldown(120)
const formattedTime = computed(() => {
const mins = Math.floor(cooldown / 60)
const secs = cooldown % 60
return `${mins}:${secs < 10 ? '0' : ''}${secs}`
})
</script>
<template>
<button @click="start" :disabled="cooldown > 0">
{{ cooldown > 0 ? `Ожидание (${formattedTime})` : 'Начать' }}
</button>
</template>
Особенности реализации
- Хранение timestamp — сохраняется момент окончания таймера, а не оставшееся время
- Автовосстановление — при загрузке страницы проверяет активный таймер
- Синхронизация — постоянно обновляет хранилище при изменении времени
Эта функция готова к использованию в любом проекте на Vue 3 и может быть легко расширена под конкретные нужды.
Добавить комментарий