Luna Tech

Tutorials For Dummies.

Vue: Async Components

2022-03-28


0. Intro

Async Components | Vue.js (vuejs.org)

基本用法

在大型的应用中,我们可以需要把 app 分解成小块,只在需要的时候从 server 加载一个 component。Vue 是通过一个 defineAsyncComponent 的功能来达成我们想要的这个效果的。

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() => {
  return new Promise((resolve, reject) => {
    // ...load component from server
    resolve(/* loaded component */)
  })
})
// ... use `AsyncComp` like a normal component

这个 function 会接收一个 loader function,loader function 会返回一个 Promise。

当你从 server 接收到了你的 component definition 时,Promise 的 resolve callback 会被调用。

我们也可以调用 reject(reason)来表示加载失败。

Wrapper Component

ES module dynamic import also returns a Promise, so most of the time we will use it in combination with defineAsyncComponent.

Vite 和 webpack 之类的 bundler 也支持这种语法,所以我们可以用它来 import Vue SFC:

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
)

上面例子中的 AsyncComp 是一个 wrapper component,只有当 component 在 page 上被渲染时才会调用 loader function。

另外,它(wrapper)会把所有的 props 都传入 inner component,所以我们可以用这个 async wrapper 来替代 original component,同时还能达到 lazy loading 的效果。

Use defineAsyncComponent when registering a component locally

import { defineAsyncComponent } from 'vue'

export default {
  // ...
  components: {
    AsyncComponent: defineAsyncComponent(() =>
      import('./components/AsyncComponent.vue')
    )
  }
}

1. Loading and Error States

因为我们用了异步操作,所以会有 loading 和 error 的状态,我们可以通过 advanced options 来处理这些 states。

const AsyncComp = defineAsyncComponent({
  // the loader function
  loader: () => import('./Foo.vue'),

  // A component to use while the async component is loading
  loadingComponent: LoadingComponent,
  // Delay before showing the loading component. Default: 200ms.
  delay: 200,

  // A component to use if the load fails
  errorComponent: ErrorComponent,
  // The error component will be displayed if a timeout is
  // provided and exceeded. Default: Infinity.
  timeout: 3000
})

假如提供了 loading component,这个 component 会在 inner component 加载的时候显示(会有默认的 200ms 延迟)。

There is a default 200ms delay before the loading component is shown - this is because on fast networks, an instant loading state may get replaced too fast and end up looking like a flicker.

假如提供了 error component,当 Promise returned by the loader function is rejected 时,会显示 error component。

你也可以定义 timeout,当 request 时间过长时显示 error component。


2. Using with Suspense

异步组件可以跟 <Suspense> 组件一起使用。

Suspense | Vue.js (vuejs.org)