# Динамические и асинхронные компоненты
Подразумевается, что уже изучили и разобрались с разделом Основы компонентов. Если нет — прочитайте его сначала.
# Динамические компоненты с keep-alive
Ранее в руководстве атрибут is
использовался для переключения между компонентами в интерфейсе с вкладками:
<component :is="currentTabComponent"></component>
Но при переключении между компонентами может потребоваться сохранять их состояние или избежать перерисовки для производительности. Например, немного доработав пример:
See the Pen Динамические компоненты: без использования keep-alive by Vue (@Vue) on CodePen.
Можно заметить, что выбрав пост, потом переключившись на вкладку Archive, а затем снова вернувшись на Posts, выбранный пост больше не отображается. Это происходит потому, что каждый раз, при переключении на другую вкладку Vue будет создавать новый экземпляр currentTabComponent
.
Обычно пересоздание динамических компонентов полезно, но в данном случае хотелось бы чтобы экземпляры компонентов вкладок кэшировались после их создания в первый раз. Для решения этой проблемы динамический компонент можно обернуть в <keep-alive>
:
<!-- Неактивные компоненты будут закэшированы! -->
<keep-alive>
<component :is="currentTabComponent"></component>
</keep-alive>
2
3
4
Проверим результат:
See the Pen Динамические компоненты: с использованием keep-alive by Vue (@Vue) on CodePen.
Теперь состояние (выбранный пост) на вкладке Posts будет сохраняться даже тогда, когда она не отрисовывается.
Подробнее о компоненте <keep-alive>
можно узнать в справочнике API.
# Асинхронные компоненты
В больших приложениях может потребоваться разделять приложение на меньшие части и загружать компоненты с сервера только когда они необходимы. Для реализации подобного Vue предоставляет метод defineAsyncComponent
:
const { createApp, defineAsyncComponent } = Vue
const app = createApp({})
const AsyncComp = defineAsyncComponent(
() =>
new Promise((resolve, reject) => {
resolve({
template: '<div>Асинхронный компонент!</div>'
})
})
)
app.component('async-example', AsyncComp)
2
3
4
5
6
7
8
9
10
11
12
13
14
Как видно, метод принимает функцию-фабрику, которая вернёт Promise
. В Promise коллбэк resolve
должен быть вызван, когда получено определение компонента с сервера. Кроме того, можно вызвать reject(reason)
для обработки неудачной загрузки.
Также можно возвращать Promise
из функции-фабрики, поэтому с Webpack 2 или более новой версии и синтаксисом ES2015 можно сделать так:
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
)
app.component('async-component', AsyncComp)
2
3
4
5
6
7
Использовать defineAsyncComponent
можно и при локальной регистрации компонента:
import { createApp, defineAsyncComponent } from 'vue'
createApp({
// ...
components: {
AsyncComponent: defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
)
}
})
2
3
4
5
6
7
8
9
10
# Использование с Suspense
Асинхронные компоненты по умолчанию считаются suspensible. Это значит, что при наличии <Suspense>
в родительской цепочке, компонент будет рассматриваться как асинхронная зависимость от этого <Suspense>
. В этом случае состояние загрузки контролируется <Suspense>
, а собственные опции компонента для загрузки, ошибки и задержки таймаута игнорируются.
Асинхронный компонент может отказаться от управления Suspense
и всегда использовать собственное состояние для загрузки, с помощью опции suspensible: false
.
Список доступных опций можно посмотреть в справочнике API