В Vue.js жизненный цикл компонента строго регламентирован. Понимание порядка вызова хуков жизненного цикла критично для корректного тестирования с использованием Vue Test Utils. Монтирование компонента в тестовой среде практически идентично реальному процессу в приложении, но имеет особенности, влияющие на доступность данных и рендеринг.
Vue.js определяет следующие хуки, участвующие в процессе монтирования:
beforeCreate Вызывается сразу после
инициализации экземпляра Vue. На этом этапе реактивность данных ещё не
настроена, а data, computed,
props и методы недоступны.
created Инициализация реактивных свойств
завершена, доступны data, props, методы и
вычисляемые свойства. DOM ещё не создан, поэтому доступ к
$el невозможен.
beforeMount Хук вызывается перед монтированием в DOM. В тестовой среде это момент перед тем, как компонент будет реально «привязан» к виртуальному DOM.
mounted Срабатывает после монтирования
компонента. В этот момент $el доступен, можно выполнять
операции, связанные с реальным DOM.
beforeUpdate и updated Эти хуки не относятся напрямую к первичному монтированию, но важны при повторных обновлениях компонента в тестах.
Для тестирования Vue-компонентов используется функция
mount или shallowMount из Vue Test
Utils. Их задача — создать экземпляр компонента, смонтировать
его и вернуть объект-обёртку (wrapper), через который
происходит взаимодействие с компонентом.
Пример базового монтирования:
import { mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
const wrapper = mount(MyComponent)
При таком вызове последовательность хуков будет следующей:
beforeCreatecreatedbeforeMountmountedЕсли в компоненте определён дочерний компонент, его монтирование произойдёт рекурсивно, соблюдая тот же порядок для каждого дочернего компонента.
Асинхронные операции в mounted Если в
mounted выполняются асинхронные задачи (например,
API-запрос через axios), монтирование завершено, но данные
ещё не обновлены. Для тестов нужно использовать
await nextTick():
import { nextTick } from 'vue'
await nextTick()
expect(wrapper.text()).toContain('Загруженные данные')Псевдо-DOM и JSDOM При запуске тестов через Jest
или Vitest компонент монтируется в виртуальном DOM (JSDOM).
$el существует, но методы, связанные с реальным браузером
(например, getBoundingClientRect), требуют
мокирования.
shallowMount и дочерние компоненты При
использовании shallowMount дочерние компоненты заменяются
заглушками. Их хуки mounted не вызываются, что важно при
тестировании взаимодействий между компонентами.
Для наглядного контроля последовательности можно добавить консольный вывод в каждый хук:
export default {
name: 'MyComponent',
data() { return { count: 0 } },
beforeCreate() { console.log('beforeCreate') },
created() { console.log('created') },
beforeMount() { console.log('beforeMount') },
mounted() { console.log('mounted') }
}
При запуске теста через mount вывод будет:
beforeCreate
created
beforeMount
mounted
Это позволяет убедиться, что все хуки вызываются в правильной последовательности.
created,
поэтому их значения доступны в хуке created.mounted. Если
компонент зависит от слотов для вычислений, их нужно передавать в тесте
при монтировании:const wrapper = mount(MyComponent, {
slots: { default: '<div>Слот</div>' }
})
mounted дочерних компонентов. Если условие
v-if изначально false, mounted
дочернего компонента не вызовется.nextTick, чтобы
убедиться, что Vue завершил реактивное обновление.mounted и выше.shallowMount, чтобы исключить рекурсивное
монтирование.async mounted) требуют ожидания
завершения промисов перед проверкой состояния компонента.| Хук | Доступность data/props | Доступность DOM |
|---|---|---|
| beforeCreate | нет | нет |
| created | да | нет |
| beforeMount | да | нет |
| mounted | да | да |
Эта таблица является ключевым ориентиром при построении тестов на монтирование, особенно когда проверяются начальные состояния, рендеринг слотов и взаимодействие с DOM.