Каждый компонент Vue проходит несколько этапов от создания до удаления. На каждом этапе можно выполнить код с помощью lifecycle hooks — функций-обработчиков.
Создание Монтирование Обновление Размонтирование
───────── ──────────── ────────── ───────────────
setup() → onBeforeMount → onBeforeUpdate → onBeforeUnmount
onMounted → onUpdated → onUnmountedimport { onMounted, onBeforeMount } from 'vue'
export default {
setup() {
onBeforeMount(() => {
// DOM ещё не создан
// Используй для подготовки данных перед рендером
console.log('Компонент готовится к монтированию')
})
onMounted(() => {
// DOM уже создан и доступен
// Используй для: fetch данных, подписок, работы с DOM
console.log('Компонент смонтирован')
fetchData()
window.addEventListener('resize', handleResize)
})
}
}onBeforeUpdate(() => {
// Реактивные данные изменились, но DOM ещё не обновлён
// Можно прочитать старое состояние DOM
})
onUpdated(() => {
// DOM обновлён в соответствии с новыми данными
// Осторожно: не изменяй реактивные данные здесь — вызовет бесконечный цикл!
})onBeforeUnmount(() => {
// Компонент ещё в DOM
// Начинай очистку
})
onUnmounted(() => {
// Компонент удалён из DOM
// Обязательно очищай подписки, таймеры, слушатели событий!
window.removeEventListener('resize', handleResize)
clearInterval(timer)
subscription.unsubscribe()
})| Options API | Composition API | Когда вызывается |
|----------------------|-----------------------|-------------------------------|
| beforeCreate | setup() (начало) | Перед инициализацией |
| created | setup() (конец) | После инициализации |
| beforeMount | onBeforeMount | Перед вставкой в DOM |
| mounted | onMounted | После вставки в DOM |
| beforeUpdate | onBeforeUpdate | Перед обновлением DOM |
| updated | onUpdated | После обновления DOM |
| beforeUnmount | onBeforeUnmount | Перед удалением из DOM |
| unmounted | onUnmounted | После удаления из DOM |
setup() {
const data = ref(null)
const loading = ref(false)
// Загрузка данных при монтировании
onMounted(async () => {
loading.value = true
data.value = await fetchUsers()
loading.value = false
})
// Очистка при размонтировании
let intervalId
onMounted(() => {
intervalId = setInterval(refreshData, 5000)
})
onUnmounted(() => {
clearInterval(intervalId)
})
return { data, loading }
}onErrorCaptured((error, instance, info) => {
console.error('Ошибка в дочернем компоненте:', error)
return false // предотвращает дальнейшее распространение ошибки
})Реализация lifecycle системы через callbacks — аналог Vue lifecycle в чистом JS
// Минималистичная lifecycle система
function createLifecycleComponent(name) {
// Хранилище callbacks для каждого хука
const hooks = {
beforeMount: [],
mounted: [],
beforeUpdate: [],
updated: [],
beforeUnmount: [],
unmounted: [],
}
// Регистрация хука (аналог onMounted, onUpdated и т.д.)
function registerHook(hookName, callback) {
if (!hooks[hookName]) {
throw new Error(`Неизвестный хук: ${hookName}`)
}
hooks[hookName].push(callback)
}
// Вызов всех callbacks для хука
function callHook(hookName, ...args) {
console.log(`[Lifecycle] ${name}: ${hookName}`)
hooks[hookName].forEach(cb => cb(...args))
}
let data = null
let isMounted = false
return {
// Регистрация хуков (аналог onMounted и т.д.)
onBeforeMount: (cb) => registerHook('beforeMount', cb),
onMounted: (cb) => registerHook('mounted', cb),
onBeforeUpdate: (cb) => registerHook('beforeUpdate', cb),
onUpdated: (cb) => registerHook('updated', cb),
onBeforeUnmount: (cb) => registerHook('beforeUnmount', cb),
onUnmounted: (cb) => registerHook('unmounted', cb),
// Методы управления жизненным циклом
mount(initialData) {
if (isMounted) throw new Error('Компонент уже смонтирован')
callHook('beforeMount')
data = initialData
isMounted = true
callHook('mounted')
},
update(newData) {
if (!isMounted) throw new Error('Компонент не смонтирован')
callHook('beforeUpdate', { old: data, new: newData })
const oldData = data
data = newData
callHook('updated', { old: oldData, new: newData })
},
unmount() {
if (!isMounted) throw new Error('Компонент не смонтирован')
callHook('beforeUnmount')
isMounted = false
data = null
callHook('unmounted')
},
getData: () => data,
}
}
// Использование
const comp = createLifecycleComponent('UserList')
// Регистрируем хуки — как в setup() с onMounted и т.д.
let timer = null
comp.onBeforeMount(() => console.log(' Готовимся к монтированию...'))
comp.onMounted(() => {
console.log(' Компонент смонтирован, запускаем таймер')
timer = 'interval_42' // Имитируем setInterval
})
comp.onBeforeUpdate(({ old: o, new: n }) => console.log(` Обновление: "${o}" -> "${n}"`))
comp.onUpdated(() => console.log(' DOM обновлён'))
comp.onBeforeUnmount(() => {
console.log(` Очищаем таймер ${timer}`)
timer = null
})
comp.onUnmounted(() => console.log(' Компонент удалён'))
// Запускаем жизненный цикл
comp.mount('initial data')
comp.update('updated data')
comp.update('final data')
comp.unmount()Каждый компонент Vue проходит несколько этапов от создания до удаления. На каждом этапе можно выполнить код с помощью lifecycle hooks — функций-обработчиков.
Создание Монтирование Обновление Размонтирование
───────── ──────────── ────────── ───────────────
setup() → onBeforeMount → onBeforeUpdate → onBeforeUnmount
onMounted → onUpdated → onUnmountedimport { onMounted, onBeforeMount } from 'vue'
export default {
setup() {
onBeforeMount(() => {
// DOM ещё не создан
// Используй для подготовки данных перед рендером
console.log('Компонент готовится к монтированию')
})
onMounted(() => {
// DOM уже создан и доступен
// Используй для: fetch данных, подписок, работы с DOM
console.log('Компонент смонтирован')
fetchData()
window.addEventListener('resize', handleResize)
})
}
}onBeforeUpdate(() => {
// Реактивные данные изменились, но DOM ещё не обновлён
// Можно прочитать старое состояние DOM
})
onUpdated(() => {
// DOM обновлён в соответствии с новыми данными
// Осторожно: не изменяй реактивные данные здесь — вызовет бесконечный цикл!
})onBeforeUnmount(() => {
// Компонент ещё в DOM
// Начинай очистку
})
onUnmounted(() => {
// Компонент удалён из DOM
// Обязательно очищай подписки, таймеры, слушатели событий!
window.removeEventListener('resize', handleResize)
clearInterval(timer)
subscription.unsubscribe()
})| Options API | Composition API | Когда вызывается |
|----------------------|-----------------------|-------------------------------|
| beforeCreate | setup() (начало) | Перед инициализацией |
| created | setup() (конец) | После инициализации |
| beforeMount | onBeforeMount | Перед вставкой в DOM |
| mounted | onMounted | После вставки в DOM |
| beforeUpdate | onBeforeUpdate | Перед обновлением DOM |
| updated | onUpdated | После обновления DOM |
| beforeUnmount | onBeforeUnmount | Перед удалением из DOM |
| unmounted | onUnmounted | После удаления из DOM |
setup() {
const data = ref(null)
const loading = ref(false)
// Загрузка данных при монтировании
onMounted(async () => {
loading.value = true
data.value = await fetchUsers()
loading.value = false
})
// Очистка при размонтировании
let intervalId
onMounted(() => {
intervalId = setInterval(refreshData, 5000)
})
onUnmounted(() => {
clearInterval(intervalId)
})
return { data, loading }
}onErrorCaptured((error, instance, info) => {
console.error('Ошибка в дочернем компоненте:', error)
return false // предотвращает дальнейшее распространение ошибки
})Реализация lifecycle системы через callbacks — аналог Vue lifecycle в чистом JS
// Минималистичная lifecycle система
function createLifecycleComponent(name) {
// Хранилище callbacks для каждого хука
const hooks = {
beforeMount: [],
mounted: [],
beforeUpdate: [],
updated: [],
beforeUnmount: [],
unmounted: [],
}
// Регистрация хука (аналог onMounted, onUpdated и т.д.)
function registerHook(hookName, callback) {
if (!hooks[hookName]) {
throw new Error(`Неизвестный хук: ${hookName}`)
}
hooks[hookName].push(callback)
}
// Вызов всех callbacks для хука
function callHook(hookName, ...args) {
console.log(`[Lifecycle] ${name}: ${hookName}`)
hooks[hookName].forEach(cb => cb(...args))
}
let data = null
let isMounted = false
return {
// Регистрация хуков (аналог onMounted и т.д.)
onBeforeMount: (cb) => registerHook('beforeMount', cb),
onMounted: (cb) => registerHook('mounted', cb),
onBeforeUpdate: (cb) => registerHook('beforeUpdate', cb),
onUpdated: (cb) => registerHook('updated', cb),
onBeforeUnmount: (cb) => registerHook('beforeUnmount', cb),
onUnmounted: (cb) => registerHook('unmounted', cb),
// Методы управления жизненным циклом
mount(initialData) {
if (isMounted) throw new Error('Компонент уже смонтирован')
callHook('beforeMount')
data = initialData
isMounted = true
callHook('mounted')
},
update(newData) {
if (!isMounted) throw new Error('Компонент не смонтирован')
callHook('beforeUpdate', { old: data, new: newData })
const oldData = data
data = newData
callHook('updated', { old: oldData, new: newData })
},
unmount() {
if (!isMounted) throw new Error('Компонент не смонтирован')
callHook('beforeUnmount')
isMounted = false
data = null
callHook('unmounted')
},
getData: () => data,
}
}
// Использование
const comp = createLifecycleComponent('UserList')
// Регистрируем хуки — как в setup() с onMounted и т.д.
let timer = null
comp.onBeforeMount(() => console.log(' Готовимся к монтированию...'))
comp.onMounted(() => {
console.log(' Компонент смонтирован, запускаем таймер')
timer = 'interval_42' // Имитируем setInterval
})
comp.onBeforeUpdate(({ old: o, new: n }) => console.log(` Обновление: "${o}" -> "${n}"`))
comp.onUpdated(() => console.log(' DOM обновлён'))
comp.onBeforeUnmount(() => {
console.log(` Очищаем таймер ${timer}`)
timer = null
})
comp.onUnmounted(() => console.log(' Компонент удалён'))
// Запускаем жизненный цикл
comp.mount('initial data')
comp.update('updated data')
comp.update('final data')
comp.unmount()Создай Vue-приложение, которое демонстрирует хуки жизненного цикла. Используй `onMounted` для запуска таймера (setInterval), который каждую секунду увеличивает счётчик `seconds`. Используй `onUnmounted` для остановки таймера. Добавь кнопку «Показать/Скрыть» для монтирования/размонтирования компонента с таймером через `v-if`.
В onMounted запусти setInterval(() => { seconds.value++ }, 1000) и сохрани ID. В onUnmounted вызови clearInterval(intervalId). Кнопка переключает visible через @click="visible = !visible". Компонент появляется/исчезает через v-if="visible".