百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

学习了 Vue defineAsyncComponent Api,它教给我这些知识?

bigegpt 2024-08-05 11:49 8 浏览

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

在其它组件中导入它:

<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是没有的,这是因为它还没有被加载。

但,如果切换按钮,我们就可以看到它了:

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

如何与异步的 setup 方法一起使用?

不管我们是否用defineAsyncComponent来异步加载,任何具有异步 setup 方法的组件都必须用<Suspense>来包装。

简而言之,创建一个异步 setup 函数是我们的一种选择,可以让我们的组件在渲染前等待一些API 调用或其他异步操作。

下面是带有异步setup的组件,使用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 解析后,然后再尝试渲染我们的组件。

Suspense的一个很好的特点是,我们可以使用槽和模板显示回退内容。回退内容将显示,直到setup函数解析,我们的组件准备好渲染。请注意,v-if已经从组件本身移到了我们的Suspense 组件上,所以所有回退内容都会显示。

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

下面是运行结果,会看到 "Loading…",然后在3秒后(setTimeout的硬编码值)组件渲染。


默认情况下,我们使用defineAsyncComponent定义的所有组件都是可Suspense的。

这意味着如果一个组件的父链中有Suspense,它将被视为该Suspense的一个异步依赖。我们的组件的加载、错误、延迟和超时选项将被忽略,而是由Suspense来处理。

总结

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

我很想知道大家对这个特性的看法。如果你已经在你的应用中使用它了,记得下面留言分享一下哦。

~完,我是小智,今天准备去干点啥~


作者:Apoorv Tyagi 译者:前端小智 来源:dev

原文:https://learnvue.co/2021/06/lazy-load-components-in-vue-with-defineasynccomponent/

相关推荐

Go语言泛型-泛型约束与实践(go1.7泛型)

来源:械说在Go语言中,Go泛型-泛型约束与实践部分主要探讨如何定义和使用泛型约束(Constraints),以及如何在实际开发中利用泛型进行更灵活的编程。以下是详细内容:一、什么是泛型约束?**泛型...

golang总结(golang实战教程)

基础部分Go语言有哪些优势?1简单易学:语法简洁,减少了代码的冗余。高效并发:内置强大的goroutine和channel,使并发编程更加高效且易于管理。内存管理:拥有自动垃圾回收机制,减少内...

Go 官宣:新版 Protobuf API(go pro版本)

原文作者:JoeTsai,DamienNeil和HerbieOng原文链接:https://blog.golang.org/a-new-go-api-for-protocol-buffer...

Golang开发的一些注意事项(一)(golang入门项目)

1.channel关闭后读的问题当channel关闭之后再去读取它,虽然不会引发panic,但会直接得到零值,而且ok的值为false。packagemainimport"...

golang 托盘菜单应用及打开系统默认浏览器

之前看到一个应用,用go语言编写,说是某某程序的windows图形化客户端,体验一下发现只是一个托盘,然后托盘菜单的控制面板功能直接打开本地浏览器访问程序启动的webserver网页完成gui相关功...

golang标准库每日一库之 io/ioutil

一、核心函数概览函数作用描述替代方案(Go1.16+)ioutil.ReadFile(filename)一次性读取整个文件内容(返回[]byte)os.ReadFileioutil.WriteFi...

文件类型更改器——GoLang 中的 CLI 工具

我是如何为一项琐碎的工作任务创建一个简单的工具的,你也可以上周我开始玩GoLang,它是一种由Google制作的类C编译语言,非常轻量和快速,事实上它经常在Techempower的基准测...

Go (Golang) 中的 Channels 简介(golang channel长度和容量)

这篇文章重点介绍Channels(通道)在Go中的工作方式,以及如何在代码中使用它们。在Go中,Channels是一种编程结构,它允许我们在代码的不同部分之间移动数据,通常来自不同的goro...

Golang引入泛型:Go将Interface「」替换为“Any”

现在Go将拥有泛型:Go将Interface{}替换为“Any”,这是一个类型别名:typeany=interface{}这会引入了泛型作好准备,实际上,带有泛型的Go1.18Beta...

一文带你看懂Golang最新特性(golang2.0特性)

作者:腾讯PCG代码委员会经过十余年的迭代,Go语言逐渐成为云计算时代主流的编程语言。下到云计算基础设施,上到微服务,越来越多的流行产品使用Go语言编写。可见其影响力已经非常强大。一、Go语言发展历史...

Go 每日一库之 java 转 go 遇到 Apollo?让 agollo 来平滑迁移

以下文章来源于GoOfficialBlog,作者GoOfficialBlogIntroductionagollo是Apollo的Golang客户端Apollo(阿波罗)是携程框架部门研...

Golang使用grpc详解(golang gcc)

gRPC是Google开源的一种高性能、跨语言的远程过程调用(RPC)框架,它使用ProtocolBuffers作为序列化工具,支持多种编程语言,如C++,Java,Python,Go等。gR...

Etcd服务注册与发现封装实现--golang

服务注册register.gopackageregisterimport("fmt""time"etcd3"github.com/cor...

Golang:将日志以Json格式输出到Kafka

在上一篇文章中我实现了一个支持Debug、Info、Error等多个级别的日志库,并将日志写到了磁盘文件中,代码比较简单,适合练手。有兴趣的可以通过这个链接前往:https://github.com/...

如何从 PHP 过渡到 Golang?(php转golang)

我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗旨,从零开始,开始学习。因为我司没有专门的Golang大牛,所以我也只能一步步自己去...