Skip to content

35.Vue 中异步组件的作用及原理

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。主要采用ES 模块动态导入配合 Vite 和 Webpack 这样的构建工具实现打包时的代码分割。

Vue2 异步组件的写法

  • 回调写法

    js
    {
      components: {
        "my-component": (resolve, reject) =>  {
          setTimeout(function () {
              resolve({
                  render(h){
                      return h('div','hello')
                  },
              });
          }, 1000);
        },
      },
    }
    {
      components: {
        "my-component": (resolve, reject) =>  {
          setTimeout(function () {
              resolve({
                  render(h){
                      return h('div','hello')
                  },
              });
          }, 1000);
        },
      },
    }
  • Promise 写法

    js
    {
      components: {
        "my-component": () => import(/* webpackChunkName:"B4" */ "./components/B4.vue"),
      },
    }
    {
      components: {
        "my-component": () => import(/* webpackChunkName:"B4" */ "./components/B4.vue"),
      },
    }
  • 对象写法

    js
    const AsyncComponent = () => ({
      // 需要加载的组件 (应该是一个 `Promise` 对象)
      component: import("./MyComponent.vue"),
      // 异步组件加载时使用的组件
      loading: LoadingComponent,
      // 加载失败时使用的组件
      error: ErrorComponent,
      // 展示加载时组件的延时时间。默认值是 200 (毫秒)
      delay: 200,
      // 如果提供了超时时间且组件加载也超时了,则使用加载失败时使用的组件。默认值是:`Infinity`
      timeout: 3000,
    });
    const AsyncComponent = () => ({
      // 需要加载的组件 (应该是一个 `Promise` 对象)
      component: import("./MyComponent.vue"),
      // 异步组件加载时使用的组件
      loading: LoadingComponent,
      // 加载失败时使用的组件
      error: ErrorComponent,
      // 展示加载时组件的延时时间。默认值是 200 (毫秒)
      delay: 200,
      // 如果提供了超时时间且组件加载也超时了,则使用加载失败时使用的组件。默认值是:`Infinity`
      timeout: 3000,
    });

异步组件原理

  • 默认渲染异步占位符节点
  • 组件加载完毕后调用 $forceUpdate 强制更新,渲染加载完毕后的组件。

Vue2 异步组件实现原理

Vue3 异步组件写法

使用defineAsyncComponent函数定义异步组件。这个函数接受一个工厂函数,工厂函数可以返回一个 Promise,当 Promise 解析后,组件将被加载并渲染。推荐的做法是将异步组件和 工程化工具 的 code-splitting 功能一起配合使用。

js
import { defineAsyncComponent } from "vue";
const AsyncComponent = defineAsyncComponent(() =>
  import("./AsyncComponent.vue")
);
import { defineAsyncComponent } from "vue";
const AsyncComponent = defineAsyncComponent(() =>
  import("./AsyncComponent.vue")
);
js
const AsyncComp = defineAsyncComponent({
  // 加载函数
  loader: () => import("./Foo.vue"),
  // 加载异步组件时使用的组件
  loadingComponent: LoadingComponent,
  // 展示加载组件前的延迟时间,默认为 200ms
  delay: 200,
  // 加载失败后展示的组件
  errorComponent: ErrorComponent,
  // 如果提供了一个 timeout 时间限制,并超时了
  // 也会显示这里配置的报错组件,默认值是:Infinity
  timeout: 3000,
});
const AsyncComp = defineAsyncComponent({
  // 加载函数
  loader: () => import("./Foo.vue"),
  // 加载异步组件时使用的组件
  loadingComponent: LoadingComponent,
  // 展示加载组件前的延迟时间,默认为 200ms
  delay: 200,
  // 加载失败后展示的组件
  errorComponent: ErrorComponent,
  // 如果提供了一个 timeout 时间限制,并超时了
  // 也会显示这里配置的报错组件,默认值是:Infinity
  timeout: 3000,
});
  • 先基于状态,默认渲染异步占位符节点。
  • 组件加载完毕后,更新状态,渲染加载完毕的组件。

Vue3 异步组件实现原理

Released under the MIT License.