Какова структура фабрики асинхронных компонентов?vue-81

Фабрика асинхронных компонентов — это функция, которая возвращает конфигурационный объект для динамической загрузки компонента. Рассмотрим детальную структуру этой фабрики.

Базовый формат фабрики

const AsyncComponent = () => ({
  // Обязательные свойства
  component: Promise<Component>,

  // Опциональные свойства
  loading?: Component,
  error?: Component,
  delay?: number,
  timeout?: number
})

Детализация структуры

1. Основное свойство component

component: import('./MyComponent.vue')
// или
component: new Promise((resolve) => {
  setTimeout(() => {
    resolve(import('./MyComponent.vue'))
  }, 1000)
})
  • Должно возвращать Promise, который резолвится в компонент
  • Обычно используется динамический import()

2. Компонент загрузки loading

loading: {
  template: '<div>Loading...</div>'
}
// или
loading: LoadingSpinner
  • Отображается во время загрузки основного компонента
  • Не показывается, если загрузка происходит быстрее delay

3. Компонент ошибки error

error: {
  template: '<div>Failed to load component</div>'
}
// или
error: ErrorComponent
  • Отображается при ошибке загрузки
  • Может включать кнопку для повторной попытки

4. Задержка показа loading

delay: 200 // миллисекунды
  • Если загрузка завершается быстрее этого времени, loading не показывается
  • Помогает избежать "мигания" при быстрой загрузке

5. Таймаут загрузки timeout

timeout: 3000 // миллисекунды
  • Если загрузка не завершилась за это время, показывается error-компонент
  • По умолчанию нет таймаута

Полный пример фабрики

const AsyncModal = () => ({
  component: import('./ComplexModal.vue')
    .then(comp => {
      // Можно модифицировать компонент перед разрешением
      comp.default.beforeMount = () => console.log('Loading modal')
      return comp
    })
    .catch(err => {
      console.error('Modal load failed', err)
      throw err
    }),

  loading: {
    template: '<div class="loading-spinner"></div>',
    mounted() {
      console.log('Loading started')
    }
  },

  error: {
    template: `
      <div class="error">
        <p>Failed to load modal</p>
        <button @click="retry">Retry</button>
      </div>
    `,
    methods: {
      retry() {
        this.$emit('retry')
      }
    }
  },

  delay: 150,
  timeout: 5000
})

Особенности работы фабрики

  1. Контекст выполнения:

    • Фабрика выполняется в контексте родительского компонента
    • Имеет доступ к this родителя (если не стрелочная функция)
  2. Повторные попытки:

    • Можно реализовать через событие retry в error-компоненте
    • Или через обертку Promise с retry-логикой
  3. Webpack-специфичные возможности:

component: import(
  /* webpackChunkName: "modal" */
  /* webpackPrefetch: true */
  './ComplexModal.vue'
)

Продвинутые паттерны

1. Фабрика с кэшированием

let cachedPromise

const AsyncCachedComponent = () => ({
  component: cachedPromise || (cachedPromise = import('./HeavyComponent.vue')),
  loading: LoadingComponent
})

2. Условная загрузка

const DynamicLoader = (featureFlag) => ({
  component: featureFlag
    ? import('./NewComponent.vue')
    : import('./OldComponent.vue')
})

3. Загрузка с зависимостями

const ComponentWithDeps = () => ({
  component: Promise.all([
    import('./MainComponent.vue'),
    import('./utils.js')
  ]).then(([component, utils]) => {
    component.default.methods = {
      ...component.default.methods,
      ...utils
    }
    return component
  })
})

Резюмируем:

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