Друзья, привет!
Практическое понимание событий жизненного цикла компонентов даёт возможность быстро анализировать и разрабатывать бизнес-задачи. Мы разберём 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. Узнать подробнее о курсе.