Vue3之异步加载组件-defineAsyncComponent

13,749 阅读2分钟

使用 Vue3 的 DefileAsyncComponent功能可让我们懒加载组件,说白了就是创建一个只有在需要时才会加载的异步组件。
这是改进初始页面加载的好方法,因为我们的应用程序将加载到较小的块中而不是必须在页面加载时加载每个组件。

在本文中,我们将学习有关defineAsyncComponent的所有知识,并学习一个懒加载弹出窗口的例子。

defineAsyncComponent 是啥?

const AsyncComp = defineAsyncComponent(
  () =>
    new Promise((resolve, reject) => {
      resolve({
        template: '<div>I am async!</div>'
      })
    })
)

defineAsyncComponent 可以接受一个返回 Promise 的工厂函数。Promise 的 resolve 回调应该在服务端返回组件定义后被调用。你也可以调用 reject(reason) 来表示加载失败。

defineAsyncComponent 可以从 vue 中导入,并使用:

import { defineAsyncComponent } from "vue"
// simple usage
const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue"))

这是defineAsyncComponent的最简单方法,对于高阶用法,defineAsyncComponent 可以接受一个对象:

const AsyncPopup = defineAsyncComponent({ 
  loader: () => import("./LoginPopup.vue"),
   // 加载异步组件时要使用的组件
  loadingComponent: LoadingComponent,
   // 加载失败时要使用的组件
  errorComponent: ErrorComponent, 
  // 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
  delay: 1000, 
  // 如果提供了 timeout ,并且加载组件的时间超过了设定值,将显示错误组件
  // 默认值:Infinity(即永不超时,单位 ms)
  timeout: 3000 
})

基础已经介绍完了,接着,我们来做个🌰。

使用 defineAsyncComponent 异步加载 Popup 组件

在这个例子中,我们将使用一个由点击按钮触发的登录弹框。我们不需要我们的应用程序在每次加载时都加载这个组件,因为只有在用户执行特定的动作时才需要它。
下面是 login 组件的实现:

// LoginPopup.vue
<template>
   <div class="popup">
       <div class="content">
           <h4> Login to your account </h4>
           <input type="text" placeholder="Email" />
           <input type="password" placeholder="Password" />
           <button> Log in </button>
       </div>
   </div>
</template>

<script>
</script>

<style scoped>
.popup {
    position: fixed;
    width: 100%;
    top: ; 
    left: ;
    height: 100%;
    background-color: rgba(, , , 0.2);
    display: flex;
    justify-content: center;
    align-items: center;
}
.content {
   min-width: 200px;
   width: 30%;
   background: #fff;
   height: 200px;
   padding: 10px;
   border-radius: 5px;
}
input[type="text"], input[type="password"] {
    border: ;
    outline: ;
    border-bottom: 1px solid #eee;
    width: 80%;
    margin:  auto;
    font-size: 0.5em;
}
button {
   border: ;
   margin-top: 50px;
   background-color:#8e44ad;
   color: #fff;
   padding: 5px 10px;
   font-size: 0.5em;
}
</style>

login 组件样式 在其它组件中导入它:

<template>
  <button @click="show = true"> Login </button>
  <login-popup v-if="show" />
</template>

<script>
import LoginPopup from './components/LoginPopup.vue'
export default {
  components: { LoginPopup },
  data() {
    return {
      show: false
    }
  }
}
</script>

我们可以使用 defineAsyncComponent,只在需要的时候加载它(按钮被点击时使用v-if来切换)。

<!-- Use defineAsyncComponent  -->
<template>
  <button @click="show = true"> Login </button>
  <login-popup v-if="show" />
</template>

<script>
import { defineAsyncComponent } from 'vue'
export default {
  components: { 
    "LoginPopup" : defineAsyncComponent(() => import('./components/LoginPopup.vue'))
  },
  data() {
    return {
      show: false
    }
  }
}
</script>

这个用法看起来和上面的差不多,不急,我们 F12 打开控制台。
如果我们不使用defineAsyncComponent,一旦我们的页面加载,我们就会看到我们的应用程序从服务器上获得LoginPopup.vue。虽然在这个例子中,性能问题不那么严重,但如果我们有几十个组件这样做,性能上多多少少还是有影响的。 然而,如果我们使用defineAsyncComponent查看同一个标签,会注意到,当我们的页面加载时,LoginPopup.vue是没有的,这是因为它还没有被加载。 但,如果切换按钮,我们就可以看到它了: 这有助于我们实现最佳性能。

总结

当构建包许多组件的大型项目时,defineAsyncComponent是非常有用的。当我们使用懒加载组件时,可以更快地加载页面,改善用户体验,最终提高应用的留存率和转换率。

原文出处:juejin.cn/post/698790…