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

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

keep-alive с динамическими компонентами

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

<component v-bind:is="currentTabComponent"></component>

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

Вы можете заметить, что если выбрать запись, переключиться на вкладку Archive, затем переключиться обратно на Posts, то больше не будет показываться выбранная запись. Это связано с тем, что каждый раз, когда вы переключаетесь на новую вкладку, Vue создаёт новый экземпляр currentTabComponent.

Пересоздание динамических компонентов обычно является полезным поведением, но в нашем случае, мы хотим чтобы экземпляры компонентов вкладок кэшировались после их создания в первый раз. Для решения этой проблемы мы можем обернуть наш динамический компонент в элемент <keep-alive>:

<!-- Неактивные компоненты будут закэшированы! -->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>

Посмотрите на результат ниже:

Теперь вкладка Posts управляет собственным состоянием (выбранной записью) даже когда не отображается. Посмотрите этот fiddle для полного примера кода.

Обратите внимание, что<keep-alive> требует чтобы у всех переключаемых компонентов было задано имя, либо через опцию name компонента, либо через локальную/глобальную регистрацию.

Подробнее с элементом <keep-alive> можно ознакомиться на странице API.

Асинхронные компоненты

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

Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// Передаём определение компонента в коллбэк resolve
resolve({
template: '<div>Я — асинхронный!</div>'
})
}, 1000)
})

Функция-фабрика принимает параметр resolve — коллбэк, который вызывается после того, как определение компонента получено от сервера. Кроме того, можно вызвать reject(reason), если загрузка по какой-либо причине не удалась. Мы используем setTimeout исключительно в демонстрационных целях; как именно получать компонент в реальной ситуации — решать только вам самим. Один из удачных подходов — это использовать асинхронные компоненты в связке с функциями Webpack по разделения кода:

Vue.component('async-webpack-example', function (resolve) {
// Специальный синтаксис require укажет Webpack
// автоматически разделить сборку на части
// для последующей асинхронной загрузки
require(['./my-async-component'], resolve)
})

Вы также можете вернуть Promise в функции-фабрике, так что с Webpack 2 и синтаксисом ES2015 можно сделать так:

Vue.component(
'async-webpack-example',
// Функция `import` возвращает Promise.
() => import('./my-async-component')
)

При использовании локальной регистрации компонентов, вы также можете непосредственно указывать функцию, которая возвращает Promise:

new Vue({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})

Если вы используете Browserify и также хотите реализовать асинхронную загрузку компонентов, нам, к сожалению, придётся вас огорчить. Сам создатель Browserify прояснил, что асинхронная загрузка “не является функцией, которую Browserify когда-либо будет поддерживать”. По крайней мере, официально. Сообщество Browserify обнаружило возможные обходные пути, которые могут быть полезны в уже существующих сложных приложениях. Но в целом мы советуем использовать Webpack, обладающий полноценной встроенной поддержкой асинхронной загрузки частей сборки.

Управление состоянием загрузки

Добавлено в версии 2.3.0+

Фабрика асинхронного компонента также может возвращать объект следующего формата:

const AsyncComponent = () => ({
// Загружаемый компонент. Значение должно быть Promise
component: import('./MyComponent.vue'),
// Компонент загрузки, используемый пока загружается асинхронный компонент
loading: LoadingComponent,
// Компонент ошибки, используемый при неудачной загрузке
error: ErrorComponent,
// Задержка перед показом компонента загрузки. По умолчанию: 200 мс.
delay: 200,
// Компонент ошибки будет отображаться, если таймаут
// был указан и время ожидания превышено. По умолчанию: Infinity.
timeout: 3000
})

Обратите внимание, что вы должны использовать Vue Router версии 2.4.0+ если вы хотите использовать указанный выше синтаксис для компонентов маршрута.