Остановка таймера
Кое-что из того, что запускает компонент, продолжается само. Интервал из setInterval() срабатывает снова и снова, пока его не остановят через clearInterval(), как вы знаете из курса по JavaScript. Если компонент запустил интервал, он же должен остановить его, когда размонтируется. Вот баннер, который каждые три секунды показывает другой десерт кафе:
<script setup>
import { onMounted, onUnmounted, ref } from "vue";
const specials = ["Морковный торт", "Чизкейк", "Мятный чай"];
const index = ref(0);
let timer;
onMounted(() => {
timer = setInterval(() => {
index.value = (index.value + 1) % specials.length;
}, 3000);
});
onUnmounted(() => {
clearInterval(timer);
});
</script>
<template>
<p>Попробуйте: {{ specials[index] }}!</p>
</template>Остаток от деления % возвращает index к 0 после последнего пункта списка. И обратите внимание:
timerобъявлена вне обоих хуков черезlet, чтобы её могли использовать оба:onMountedсохраняет в ней идентификатор интервала, аonUnmountedостанавливает этот интервал.- Интервал запускается в
onMounted. В начале<script setup>он тоже работал бы, но вonMountedон стартует, когда компонент уже на странице, а два хука читаются как пара: что запустил один, останавливает другой.
А если бы onUnmounted не было? Интервал ничего не знает о компонентах. Когда Vue убирает баннер со страницы, интервал продолжает работать, пока открыта страница, и продолжает менять реф, который ничего не показывает. Каждый раз, когда баннер показывают снова, новый компонент запускает ещё один интервал. На странице этого не видно, зато видно в консоли — этим и займётся упражнение.
То же относится к ещё не сработавшему setTimeout() и к обработчику, добавленному через window.addEventListener(): что запустил компонент, то останавливает onUnmounted.
Типичная ошибка: const timer = setInterval(…) внутри onMounted. Эта константа существует только внутри функции onMounted, поэтому onUnmounted не сможет остановить интервал.
Задание
- 1
В
Timer.vueзапустите интервал вonMounted: каждые 1000 миллисекунд он увеличиваетsecondsна 1 и выводит время в консоль черезconsole.log(`Ожидание: ${seconds.value} с`);. - 2
Нажмите
Скрыть таймери посмотрите на консоль: таймера уже нет, а строки продолжают появляться. НажмитеПоказать таймер: теперь в консоли чередуются значения времени двух интервалов. Исправьте: объявитеlet timer;надonMounted, сохраните в ней идентификатор интервала и остановите интервал вonUnmountedчерезclearInterval(timer).