Каждый компонент 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()Реализуй класс `Component` с системой lifecycle hooks. Методы регистрации (могут вызываться несколько раз — callbacks накапливаются): - `onMount(cb)` — регистрирует callback для события монтирования - `onUpdate(cb)` — регистрирует callback для события обновления - `onDestroy(cb)` — регистрирует callback для события уничтожения Методы жизненного цикла: - `mount()` — вызывает все `onMount` callbacks в порядке регистрации - `update(newData)` — сохраняет newData, вызывает все `onUpdate` callbacks с newData - `destroy()` — вызывает все `onDestroy` callbacks, затем очищает все списки callbacks ``` const comp = new Component() comp.onMount(() => console.log('mounted 1')) comp.onMount(() => console.log('mounted 2')) comp.onUpdate(data => console.log('updated:', data)) comp.onDestroy(() => console.log('destroyed')) comp.mount() // mounted 1 // mounted 2 comp.update({ x: 1 }) // updated: { x: 1 } comp.destroy() // destroyed ```
В constructor создай три массива. В onMount/onUpdate/onDestroy — пуш в соответствующий массив. В mount — forEach по _mountCallbacks. В update — сохрани newData и forEach по _updateCallbacks передавая newData. В destroy — forEach по _destroyCallbacks, затем обнули все три массива.
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке