# Экземпляры приложения & компонента

# Создание экземпляра приложения

Создание любого приложения Vue начинается с создания нового экземпляра приложения с помощью функции createApp:

const app = Vue.createApp({
  /* опции */
})
1
2
3

Экземпляр приложения используется для регистрации «глобальных» вещей, которые будут затем использоваться компонентами внутри этого приложения. Подробнее познакомимся дальше в руководстве, но в качестве небольшого примера:

const app = Vue.createApp({})

app.component('SearchInput', SearchInputComponent)
app.directive('focus', FocusDirective)
app.use(LocalePlugin)
1
2
3
4
5

Большинство из методов экземпляра приложения возвращают этот же экземпляр, что позволяет составлять вызовы в цепочку:

Vue.createApp({})
  .component('SearchInput', SearchInputComponent)
  .directive('focus', FocusDirective)
  .use(LocalePlugin)
1
2
3
4

Полный список API приложения можно посмотреть в разделе Справочник API.

# Корневой компонент

Опции, передаваемые в createApp, используются для настройки корневого компонента. При монтировании приложения он используется как стартовая точка для отрисовки.

Приложению требуется примонтироваться в DOM-элемент. Например, если потребуется примонтировать приложение Vue в <div id="app"></div>, то необходимо передать #app:

const RootComponent = {
  /* опции */
}
const app = Vue.createApp(RootComponent)
const vm = app.mount('#app')
1
2
3
4
5

В отличие от большинства других методов приложения, mount не возвращает экземпляр приложения — вместо этого он возвращает экземпляр корневого компонента.

Vue хоть и не реализует в полной мере паттерн MVVM (opens new window), но архитектура фреймворка во многом вдохновлена им. Поэтому, как правило, переменную с экземпляром приложения называют vm (сокращение от ViewModel).

Пусть все примеры на этой странице и нуждаются лишь в одном компоненте, большинство реальных приложений организованы в дерево вложенных, многократно переиспользуемых компонентов. Например, дерево компонентов приложения todo-списка может быть таким:

Корневой компонент
└─ TodoList
   ├─ TodoItem
   │  ├─ DeleteTodoButton
   │  └─ EditTodoButton
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics
1
2
3
4
5
6
7
8

Каждый компонент будет иметь свой собственный экземпляр компонента vm. У некоторых компонентов, таких как TodoItem, вероятно, будет несколько экземпляров, отображаемых в один момент времени. Все экземпляры компонентов в этом приложении будут иметь один и тот же экземпляр приложения.

Подробнее на системе компонентов остановимся позже. Сейчас достаточно запомнить, что корневой компонент на самом деле ничем не отличается от любого другого компонента. Опции конфигурации такие же, как и поведение соответствующего экземпляра компонента.

# Свойства экземпляра компонента

Раньше в руководстве встречались свойства data. Все свойства, объявленные в data, доступны через экземпляр компонента:

const app = Vue.createApp({
  data() {
    return { count: 4 }
  }
})

const vm = app.mount('#app')

console.log(vm.count) // => 4
1
2
3
4
5
6
7
8
9

Есть и другие опции компонента, добавляющие в экземпляр компонента пользовательские свойства, например methods, props, computed, inject и setup. Подробнее о каждой из них поговорим далее в руководстве. Все свойства экземпляра компонента, независимо от того, как они определены, будут доступны в шаблоне компонента.

Через экземпляр компонента Vue также предоставляет доступ к некоторым встроенным свойствам, например $attrs и $emit. Такие свойства всегда именуются с префиксом $, чтобы избежать конфликта имён с пользовательскими свойствами.

# Хуки жизненного цикла

При создании каждый экземпляр проходит через серию шагов инициализации — например, устанавливает наблюдение за данными, компилирует шаблон, монтирует экземпляр в DOM, обновляет DOM при изменении данных. Между шагами вызываются функции, называемые хуками жизненного цикла, предоставляющие возможность выполнять код на определённых этапах.

Например, хук created можно использовать для запуска кода после создания экземпляра:

Vue.createApp({
  data() {
    return { count: 1 }
  },
  created() {
    // `this` указывает на экземпляр vm
    console.log('счётчик: ' + this.count) // => "счётчик: 1"
  }
})
1
2
3
4
5
6
7
8
9

Также есть и другие хуки, которые будут вызываться на различных этапах жизненного цикла экземпляра, например mounted, updated и unmounted. Все хуки вызываются с контекстом this, указывающим на текущий активный экземпляр, который их вызвал.

Совет

Не используйте стрелочные функции (opens new window) в свойствах экземпляра и в коллбэках, например created: () => console.log(this.a) или vm.$watch('a', newVal => this.myMethod()). Так как стрелочные функции не имеют собственного this, то this в коде будет обрабатываться как любая другая переменная и её поиск будет производиться до тех пор, пока она не будет найдена в области видимости выше, что часто приводит к ошибкам, таким как Uncaught TypeError: Cannot read property of undefined или Uncaught TypeError: this.myMethod is not a function.

# Диаграмма жизненного цикла

Ниже представлена диаграмма жизненного цикла экземпляра. Необязательно запоминать всё полностью прямо сейчас, но, по мере изучения и практики разработки, будет полезно к ней обращаться.

Хуки жизненного цикла экземпляра