# Динамические и асинхронные компоненты
Подразумевается, что вы уже изучили и разобрались с разделом Основы компонентов. Если нет — прочитайте его сначала.
# Динамические компоненты с keep-alive
Ранее, атрибут is
использовался для переключения между компонентами в интерфейсе с вкладками:
<component :is="currentTabComponent"></component>
Однако при переключении между этими компонентами может возникнуть необходимость сохранить их состояние или избежать их перерисовку в целях производительности. Например при небольшой доработки интерфейса с вкладками:
See the Pen Dynamic components: without 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 Dynamic components: with 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>I am async!</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