# Динамические и асинхронные компоненты

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

# Динамические компоненты с keep-alive

Ранее, атрибут is использовался для переключения между компонентами в интерфейсе с вкладками:

<component :is="currentTabComponent"></component>
1

Однако при переключении между этими компонентами может возникнуть необходимость сохранить их состояние или избежать их перерисовку в целях производительности. Например при небольшой доработки интерфейса с вкладками:

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>
1
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)
1
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)
1
2
3
4
5
6
7

Также можно использовать defineAsyncComponent при локальной регистрации компонента:

import { createApp, defineAsyncComponent } from 'vue'

createApp({
  // ...
  components: {
    AsyncComponent: defineAsyncComponent(() =>
      import('./components/AsyncComponent.vue')
    )
  }
})
1
2
3
4
5
6
7
8
9
10

# Использование с Suspense

Асинхронные компоненты по умолчанию считаются suspensible. Это означает, что если имеется <Suspense> в родительской цепочке, то компонент будет рассматриваться как асинхронная зависимость от этого <Suspense>. В таком случае состояние загрузки будет контролироваться <Suspense>, а собственные опции компонента для загрузки, ошибки, задержки и таймаута будут проигнорированы.

Асинхронный компонент может отказаться от управления Suspense и всегда использовать собственное состояние для загрузки, с помощью опции suspensible: false.

Список доступных опций можно посмотреть в справочнике API

Deployed on Netlify.
Последнее обновление: 2021-01-18, 21:11:09 UTC