Найти тему
DEVHOUSE ACADEMY

ДЕЛАЕМ ТАЙМЕР ПОШАГОВО НА ФРЕМВОРКЕ VueJS

Оглавление

ДЛЯ ТЕХ, КТО ПРЯМО СЕЙЧАС ХОЧЕТ СЕБЯ ПОПРОБОВАТЬ ВО FRONTEND👇

Даем пошаговую инструкцию того, как сделать компонент для таймера обратного отсчета на сайт💡

Потребность в нем возникает довольно часто, например, отсчет до старта продаж или до конца срока действия акции и пр.

Скоро «ЧЁРНАЯ ПЯТНИЦА», сделайте обратный отсчёт для интернет-магазина.

В качестве фремворка будем использовать VueJS 3 версии, но под любой другой фремворк его адаптировать будет не сложно.

ЭТАП 1

Сначала создадим демонстрационный проект для тестирования нашего компонента.

Для этого нужно будет установить среду для сборки NodeJS c официального сайта: https://nodejs.org/ru

Также будем использовать IDE VSCode, ее тоже можно скачать бесплатно с официального сайта: https://code.visualstudio.com

Создаем новую папку для проектов открываем ее в vscode и запускаем в нем терминал.

Открытие папки vscode
Открытие папки vscode
Открытие терминала
Открытие терминала

В терминале вбиваем команду для создания нового проекта vuejs (попутно он предложит установить утилиту vue-create, а потом предложит указать название проекта и другие опции - там пока можно везде выбрать No):

```sh

npm create vue@latest

```

Переходим в терминале в папку проекта:

```sh

cd название проекта

```

Устанавливаем локально зависимости:

```sh

npm i

```

Вот так выглядит терминал
Вот так выглядит терминал

Далее для локального запуска проекта нужно будет вбить в терминал:

```sh

npm run dev

```

Запустится локальный стенд и будет указана ссылка, по которой можно посмотреть результат (по мере обновления кода и его сохранения стенд будет автоматически обновляться).

Результат команды npm run dev
Результат команды npm run dev

ЭТАП 2

Теперь создадим компонент Timer.vue в папке /src/components/ со следующим содержимым:

```js

// Timer.vue

<script setup>

</script>

<template>

<div class="timer">

12 дн. 5 ч. 32 мин. 48 сек.

</div>

</template>

```

В нем сразу добавим блок с примером отображения результата.

Добавим теперь его на главный экран, чтобы можно было наблюдать результат:

```js

// App.vue

<script setup lang="ts">

import Timer from './components/Timer.vue'

</script>

<template>

<main>

<Timer />

</main>

</template>

```

При запуске приложения должно получиться следующее:

-5

Так как мы хотим сделать компонент переиспользуемым, добавим параметр - целевая дата (до которой нужно отсчитывать время)

```js

// App.vue

...

<main>

<Timer target-date="2024-06-01T12:53:44Z" />

</main>

...

```

Дата в формате ISO и обязательно UTC, так как момент времени един для всех часовых поясов.

В самом компоненте таймера добавим чтение этого параметра:

```js

// Timer.vue

...

const props = defineProps({ targetDate: String })

const target = new Date(props.targetDate)

...

```

ЭТАП 3

Теперь создадим реактивный объект, который будет хранить все данные об оставшемся времени до целевой даты.

И инициализируем его нулевыми значениями:

```js

// Timer.vue

...

// объект с нулевыми значениями

const nullDiff = {

days: 0,

hours: 0,

minutes: 0,

seconds: 0,

}

// реактивная переменная для хранения вычисленных значений (изначально хранит данные из nullDiff)

const diff = reactive(nullDiff)

...

```

Добавим в верстку теперь данные из этой переменной:

```js

// Timer.vue

...

<template>

<div class="timer">

{{ diff.days }} дн. {{ diff.hours }} ч. {{ diff.minutes }} мин. {{ diff.seconds }} сек.

</div>

</template>

...

```

Теперь реализуем функцию для вычисления значений таймера:

```js

// Timer.vue

...

const updateDiff = () => {

const now = new Date() // сохраняем в переменную текущее время

const result = new Date(target.getTime() - now.getTime()) // вычисляем разницу в миллисекундах и преобразуем в формат даты для удобного чтения отдельных позиций: дней, часов и т д

// если дата находится в прошлом, то пусть таймер отображает нулевые значения

if (result <= 0) {

Object.assign(diff, nullDiff)

return

}

// из разницы (которая была преобразована в формат даты) достаем все позиции

Object.assign(diff, {

days: result.getUTCDate() - 1, // так как у формата даты минимальное значение 1, необходимо вычесть единицу

hours: result.getUTCHours(),

minutes: result.getUTCMinutes(),

seconds: result.getUTCSeconds(),

})

}

...

```

Поясним, зачем мы разницу в миллисекундах преобразуем в формат даты.

Команда target.getTime() возвращает количество миллисекунд до этого момента, начиная с 1 января 1970 года.

Когда мы берем разницу target.getTime() - now.getTime(), мы результат получаем тоже в мс.

Доставать оттуда значения дней, часов и пр. довольно сложно и есть риск ошибиться.

Когда мы преобразуем эту разницу снова в Date, то получаем что-то вроде даты 1970-01-14Т22:21:15.

Отсюда уже легко вычленить отдельные позиции.

Теперь при обновлении страницы получим актуальное значение таймера до выбранной даты.

-6

Однако секунды остановились и не меняются.

Для этого необходимо завести встроенный таймер (буду называть его js-таймер, чтобы не путать), чтобы он каждую секунду обновлял значение:

```js

// Timer.vue

...

const UPDATE_INTERVAL = 1000 // инервал обновления 1000 миллисекунл = 1 секунда

const timerID = 0 // id js-таймер, для того чтобы потом можно было его удалить

onMounted(() => {

// при монтировании компонента создадим js-таймер, который будет запускать функцию обновления нашего таймера

const timerID = setInterval(updateDiff, UPDATE_INTERVAL)

updateDiff() // запускаем функцию первый раз, чтобы пользователь сразу видел актуальное время

})

onUnmounted(() => {

// при удалении компонента удаляем js-таймер

clearInterval(timerID)

})

...

```

В итоге получаем рабочий таймер, который отсчитывает время до определенного момента.

Когда он дойдет до конца, то остановится:

-7

Вот полный код компонента:

```js

// Timer.vue

<script setup>

import { reactive, onMounted, onUnmounted } from 'vue'

const props = defineProps({ targetDate: String })

const target = new Date(props.targetDate)

// вычисление значений таймера

const nullDiff = {

days: 0,

hours: 0,

minutes: 0,

seconds: 0,

}

const diff = reactive(nullDiff)

const updateDiff = () => {

const now = new Date()

const result = new Date(target.getTime() - now.getTime())

if (result <= 0) {

Object.assign(diff, nullDiff)

return

}

console.log(result)

Object.assign(diff, {

days: result.getUTCDate() - 1,

hours: result.getUTCHours(),

minutes: result.getUTCMinutes(),

seconds: result.getUTCSeconds(),

})

}

// обновление таймера

const UPDATE_INTERVAL = 1000 //ms

const timerID = 0

onMounted(() => {

const timerID = setInterval(updateDiff, UPDATE_INTERVAL)

updateDiff()

})

onUnmounted(() => {

clearInterval(timerID)

})

</script>

<template>

<div class="timer">

{{ diff.days }} дн. {{ diff.hours }} ч. {{ diff.minutes }} мин. {{ diff.seconds }} сек.

</div>

</template>

...

```

Таймер - один из простых элементов, попробуйте его сделать по нашей инструкции.

Если в процессе написания кода возникнут вопросы, пишите их в комментариях.

Наш эксперт поможет исправить ошибки✔️