乐趣区

关于前端:Vuejs-中使用defineAsyncComponent-延迟加载组件

应用 Vue 3 的 defineAsyncComponent 个性能够让咱们提早加载组件。这意味着它们仅在须要时从服务器加载。

这是改善初始页面加载的好办法,因为咱们的应用程序将以较小的块加载,而不用在页面加载时加载每个组件。

在本教程中,咱们将学习 defineAsyncComponent 的全部内容,并看一个例子,该例子将一个弹出窗口的加载推延到咱们的应用程序须要的时候。

好了,让咱们开始吧。

什么是 defineAsyncComponent

// SOURCE: https://v3.vuejs.org/guide/component-dynamic-async.html
const AsyncComp = defineAsyncComponent(() =>
    new Promise((resolve, reject) => {
      resolve({template: '<div>I am async!</div>'})
    })
)

defineAsyncComponent 承受一个返回 Promise 的工厂函数。当咱们胜利地从服务器获取组件时,这个 Promise 应该会被 resolve,如果呈现谬误则会被 reject

要应用它,咱们必须从 Vue 中导入它,而后能力在脚本的其余部分中应用它。

咱们也能够应用工厂函数中的 import,轻松地从其余文件中增加 Vue 组件。

import {defineAsyncComponent} from "vue" 

// 简略应用
const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue"))

这是应用 defineAsyncComponent 的最简略办法,但咱们也能够传入一个残缺的选项对象,配置几个更高级的参数。

// with options 
const AsyncPopup = defineAsyncComponent({loader: () => import("./LoginPopup.vue"),
  loadingComponent: LoadingComponent, /* 在加载时显示 */
  errorComponent: ErrorComponent, /* 显示是否有谬误 */
  delay: 1000, /* 在显示加载组件之前提早毫秒 */
  timeout: 3000 /* 这个毫秒之后的超时 */
})

就我集体而言,我发现自己更常常应用第一种较短的语法,它对我的大多数应用状况都无效,但这齐全取决于你。

就这么简略,让咱们进入咱们的例子。

应用 defineAsyncComponent 提早加载弹出组件

在本例中,咱们将应用一个由单击按钮触发的登录弹出窗口。

每当咱们的应用程序加载时,咱们不须要咱们的应用程序加载此组件,因为只有在用户执行特定操作时才须要它。

所以这就是咱们的登录组件的样子,它只是通过用 position: fixed 将屏幕的其余部分涂黑来创立一个弹出窗口,并且有一些输出和一个提交按钮。

<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>

而不是像咱们通常那样导入它并将其纳入咱们的 components 选项中。

<!-- "Standard" way of doing things -->
<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>

尽管这在咱们应用咱们的应用程序时可能看起来是一样的,但让咱们查看元素 > 网络来了解这个小而重要的区别。

如果咱们不应用 defineAsyncComponent,一旦咱们的页面加载,咱们就会看到咱们的应用程序从服务器上取得 LoginPopup.vue。尽管在这个例子中,这可能不是最大的性能问题,但它依然会减慢加载速度,如果咱们有几十个组件这样做,它真的会加起来。

然而,如果咱们应用 defineAsyncComponent 查看同一个选项卡,咱们会留神到当咱们的页面加载时,LoginPopup.vue 不见了,这是因为它还没有加载。

然而一旦咱们点击咱们的按钮并通知咱们的应用程序显示咱们的弹出窗口,这时它就会从服务器加载,咱们能够在网络标签中看到它。

这有助于咱们实现最佳性能。咱们只想在咱们的页面初始加载时加载须要的组件。有条件渲染的组件在咱们的页面加载时往往是不须要的,所以为什么要让咱们的应用程序加载它们呢?

如何应用异步设置性能

无论咱们是否应用 defineAsyncComponent 提早加载,任何具备异步设置性能的组件都必须用 <Suspense> 包装。

简而言之,创立一个异步设置函数是咱们的一个抉择,能够让咱们的组件在渲染前期待一些 API 调用或其余异步动作。

这是咱们具备异步设置的组件。它应用 setTimeout() 模仿 API 调用。

<template>
  <div class="popup">
    <div class="content">
      <p> Loaded API: {{article}} </p>
      <h4> Login to your account </h4>
      <input type="text" placeholder="Email" />
      <input type="password" placeholder="Password" />
      <button> Log in </button>
    </div>
  </div>
</template>

<script>
const getArticleInfo = async () => {
  // wait 3 seconds to mimic API call
  await new Promise(resolve => setTimeout(resolve, 1000));
  const article = {
    title: 'My Vue 3 Article',
    author: 'Matt Maribojoc'
  }
  return article
}
export default {async setup() {const article = await getArticleInfo()
    console.log(article)
    return {article}
  }
}
</script>

咱们能够在有或没有 defineAsyncComponent 的状况下将它导入到咱们的组件中

import LoginPopup from './components/LoginPopup.vue'
// OR 
const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue"))

然而如果咱们想让它在咱们的模板中渲染,咱们须要将它包装在一个 Suspense 元素中。这将期待咱们的 setup 函数在尝试渲染咱们的组件之前解析。

<template>
  <button @click="show = true"> Login </button>
  <Suspense v-if="show">
    <template #default>
      <login-popup  />
    </template>
    <template #fallback>
      <p> Loading... </p>
    </template>
  </Suspense>
</template>

这就是后果。用户会看到 “ 正在加载 ……”,而后在 3 秒后(咱们的 setTimeout 的硬编码值),咱们的组件将渲染。

默认状况下,咱们应用 defineAsyncComponent 定义的所有组件都是可暂停的。

这意味着如果一个组件的父链中有 Suspense,它将被视为该 Suspense 的一个异步依赖。咱们的组件的加载、谬误、提早和超时选项将被疏忽,而是由 Suspense 来解决。

最初的想法

defineAsyncComponent 在创立有几十个组件的大型项目时是有益处的。当咱们进入到懈怠加载组件时,咱们能够有更快的页面加载工夫,改善用户体验,并最终进步你的应用程序的保留率和转换率。

我想晓得你对这个性能的认识。如果你曾经在你的利用中应用它了,请在上面的评论中通知我。

退出移动版