Друзья, привет!
Практическое понимание событий жизненного цикла компонентов даёт возможность быстро анализировать и разрабатывать бизнес-задачи. Мы разберём 7 событий жизненного цикла компонентов на примере Composition API в Vue3 фреймворке.
onBeforeMount()
Событие жизненного цикла срабатывает до появления компонента в DOM дереве.
Первым из всех событий жизненного цикла имеет доступ к реактивным данным.
Компонент создан. Первая фаза рендеринга не началась. Компонента ещё нет в DOM дереве.
Сигнатура метода
onBeforeMount(callback(): void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример: получение данных с сервера
Мы можем запросить данные с сервера сразу после настройки реактивного состояния компонента в <script setup>. Компонент ещё не виден пользователю, но необходимые данные с сервера уже запрошены.
// <script setup> import {onBeforeMount, ref} from "vue"; const users = ref<{id: number, name: string}[]>([]); onBeforeMount(async () => { const response = await fetch("https://jsonplaceholder.typicode.com/users"); users.value = await response.json() })
// template <ul> <li v-for="user of users">{{user.name}}</li> </ul>
Пример: регистрация событий DOM
Используем onBeforeMount, когда нам необходимо отслеживать в компоненте глобальные события нашего приложения. Например, можно подписаться на событие изменения размера окна.
// <script setup> import {onBeforeMount} from "vue"; const width = ref(window.innerWidth) const reszie = () => { width.value = window.innerWidth; } onBeforeMount(() => { window.addEventListener('resize', resize); })
onMounted()
Событие жизненного цикла срабатывает после появления компонента в DOM дереве.
Компонент считается смонтированным, если все дочерние синхронные компоненты смонтированы.
Компонент отображается в DOM дереве.
Сигнатура метода
onMounted(callback: () => void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример: инициализация сторонней библиотеки
Для примера возьмем библиотеку отображения графиков Chart.js. Данная библиотека требует на вход ссылку на DOM элемент. Хук onMounted срабатывает после отображения шаблона компонента в DOM дереве. Реактивная ссылка chartRef будет иметь указатель на canvas элемент.
// <script setup> import {onMounted, ref} from "vue"; const canvasRef = ref<HTMLCanvasElement | null>(null) const chartRef = shallowRef<ChartJS | null>(null) onMounted(() => { chartRef.value = new ChartJS(canvasRef.value, config as any) })
// template <canvas ref="canvasRef"/>
Пример: получение данных из внешнего источника
Если после отображения компонента нам необходимы дополнительные данные с сервера, то используем onMounted() событие.
// <script setup> import {onMounted, ref} from "vue"; const users = ref<{id: number, name: string}[]>([]); onMounted(async () => { const response = await fetch("http://localhost:3000/users"); users.value = await response.json() })
// template <ul> <li v-for="user of users">{{user.name}}</li> </ul>
Пример: регистрация событий DOM
Используем onMounted, когда нам необходимо отслеживать в компоненте глобальные события нашего приложения. Нам важно, чтобы наш компонент был виден на экране во время создания подписки.
// <script setup> import {onMounted, ref} from "vue"; const width = ref(window.innerWidth) const reszie = () => { width.value = window.innerWidth; } onMounted(() => { window.addEventListener('resize', resize) })
onBeforeUpdate()
Срабатывает до обновления DOM дерева. Используется для взаимодействия с DOM деревом. Безопасно изменять состояние компонента.
Сигнатура метода
onBeforeUpdate(callback: () => void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример: удаление ссылок на компоненты
Если нам необходимо хранить массив ссылок на элементы шаблона нашего компнента, то при изменении кол-ва элементов, необходимо обновить реактивные данные. Если мы используе ref с v-for в шаблоне компонента, то нет гарании, что массив ref будет хранить туже последовательность, что и данные в v-for. Нам нужно самим управлять массивом HTML элементов.
// <script setup> import {onBeforeUpdate, shallowRef} from "vue"; const liElements = shallowRef<(HTMLLIElement | undefined) []>([]) onBeforeUpdate(() => { liElements.value = [] }) const onUpdateRef = (e: any, index: number) => { liElements.value[index] = e }
// template <li v-for="(user, index) in users" :ref="e => onUpdateRef(e, index)" :key="user.id" tabindex="1" @click="onItemClick(user.id)">{{user.name}}</li>
onUpdated()
Callback функция срабатывает после изменения DOM дерева компонентов в соответствии с реактивным сотоянием компонента. Различные изменения состояния объединяются в один цикл рендеринга компонента для отпимизации производительности.
Сигнатура метода
onMounted(callback: () => void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример: получение применённого реактивного стостояния в DOM дереве.
Пользователь нажимает на кнопку, реактивное состояние компонента изменяется и применяется к DOM. Callback в onUpdated методе содержит одинаковые данные как в DOM, так и в реактивном состоянии.
// <script setup> import {onUpdated, ref} from "vue"; const count = ref(0) const divRef = ref<HTMLDivElement | null>(null) onUpdated(() => { const divCountValue = parseInt(divRef.value.innerHTML) // divCountValue === count => true console.log(divCountValue === count.value) })
// template <div ref="divRef">{{count}}</div> <button @click="count++">Count</button>
onBeforeUnmounted()
Вызов происход до момента удаления компонента. Реактивные состояния компонента активны. Расположить логику, которая удалит события или подчистит использование памяти, хорошая мысль
Сигнатура метода
onBeforeUnmounted(callback: () => void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример: удаление таймеров созданных в компоненте
Регистрация событий, таймеров происходит в onBeforeMount или onMounted в зависимости от целей задачи. Очистка зарегестрированных обработчиков выполняется в onBeforeUnmount.
// <script setup> let intervalId; onMounted(() => { intervalId = setInterval(() => { // logic here },1000) }) onBeforeUnmount(() => { clearInterval(intervalId) })
onUnmounted()
Компонент уничтожен. Все реактивные состояния остановлены. Мы можем взаимодействовать с созданными подписками таймеров, DOM или подключением к серверу.
Сигнатура метода
onUnmounted(callback: () => void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример использования
Удаление обработчика события изменения окна.
// <script setup> import {onMounted, onUnmounted, ref} from "vue"; const size = ref({width: window.innerWidth, height: window.innerHeight}) const resize = () => { size.value.width = window.innerWidth size.value.height = window.innerHeight } onMounted(() => { window.addEventListener('resize', resize) }) onUnmounted(() => { window.removeEventListener('resize', resize) })
onErrorCaptured()
Метод предоставляет возможность перехватывать ошибки в компоненте. Ошибки кода в <script setup>, рендеринга, обработчиков событий, функций жизненного цикла компонента, наблюдателей, директив и переходов.
Сигнатура метода
onBeforeUnmounted(callback: () => void): void
Выполнение функции callback синхронное. Можно выполнять асинхронный код в callback функции. Vue фреймворк не будет ждать завершение исполнения асинхронного кода.
Пример: отображение ошибки из дочернего компонента
Важно отображать ошибку без влияния на состояние компонента, которое привело к ошибки, иначе будет бесконечный цикл.
// <script setup> const error = ref<string | undefined>() onErrorCaptured((err, instance, info) =>{ error.value = err.message; })
// template <ErrorComponent v-if="!error"/> <div v-if="error">Error: {{error}}</div>
Резюме
Понимание событий жизненного цикла компонента упрощает реализацию бизнес-задач.
Lifecycle Hook | Когда | Для чего |
onBeforeMount | до вставки в DOM | регистрация глобального события, получение данных из внешнего источника |
onMounted | после вставки в DOM | регистрация глобального события, получить дополнительные данные из внешнего источника, встроить внешние библиотекти |
onBeforeUpdate | до обновления DOM | получить состояние DOM до обновления |
onUpdated | после обновления DOM | получить обновлённое состояние DOM |
onBeforeUnmount | до уничтожения компонента | удалить глобальные события с возможностью использования реактивных данных, разорвать соединения с внешними источниками |
onUnmounted | компонент уничтожен | удалить глобальные события, разорвать соединения с внешними источниками |
onErrorCaptured | во время возникновения ошибки на этапе жизни компонента | поймать ошибки компонента |
Ссылка на исходный код.
Статья подготовлена в преддверии старта курса Vue.js Developer. Узнать подробнее о курсе.
