当前位置: 首页 > news >正文

Vue3 异步组件(懒加载组件)

Vue3 异步组件(懒加载组件)

  • 1. 基本用法
    • 1.1 基本语法(defineAsyncComponent )
    • 1.2 使用示例
      • 1.2.1 非异步组件(正常 import,会导致初始加载时间变长)
      • 1.2.2 异步组件(使用 defineAsyncComponent 异步加载组件,减少初始加载时间 )
  • 2. 使用细节
    • 2.1 注册方式
      • 2.1.1 全局注册
      • 2.1.2 局部注册(通常配合 is 和 v-if 进行使用)
    • 2.2 加载与错误状态(delay 和 timeout 无效)

1. 基本用法

异步组件,就是需要时才异步加载的组件

1.1 基本语法(defineAsyncComponent )

在 Vue3 中,我们可以通过 defineAsyncComponent 函数来实现异步加载组件:

import { defineAsyncComponent } from 'vue'const AsyncComp = defineAsyncComponent(() => {return new Promise((resolve, reject) => {// ...从服务器获取组件resolve(/* 获取到的组件 */)})
})
// ... 像使用其他一般组件一样使用 `AsyncComp`

ES 模块动态导入也会返回一个 Promise,所以多数情况下我们会将它和 defineAsyncComponent 搭配使用:

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

最后得到的 AsyncComp 是一个外层包装过的组件,仅在页面需要它渲染时才会调用加载内部实际组件的函数。它会将接收到的 props 和插槽传给内部组件,所以你可以使用这个异步的包装组件无缝地替换原始组件,同时实现延迟加载。

1.2 使用示例

1.2.1 非异步组件(正常 import,会导致初始加载时间变长)

在我们的项目中,通常我们会使用 import 直接导入需要的组件。

父组件 App.vue:

<template><div id="app"><button @click="currentComponent = A">访问A组件</button><button @click="currentComponent = B">访问B组件</button><component :is="currentComponent" v-if="currentComponent"></component></div>
</template><script setup>
import { shallowRef } from 'vue'
import A from '@/components/A.vue'
import B from '@/components/B.vue'
const currentComponent = shallowRef(null)
</script><style lang="scss" scoped>
button {margin-right: 10px;
}
</style>

这样在应用启动时就会立即加载所有被导入的组件,从而导致初始的加载时间变长,特别是当组件特别多的时候。

子组件 A.vue:

<template><div>这是A组件</div>
</template><script setup></script><style lang="scss" scoped></style>

子组件 B.vue:

<template><div>这是B组件</div>
</template><script setup></script><style lang="scss" scoped></style>

1.2.2 异步组件(使用 defineAsyncComponent 异步加载组件,减少初始加载时间 )

此时我们就可以使用异步组件来进行优化

<template><div id="app"><button @click="loadComponent('A')">访问A组件</button><button @click="loadComponent('B')">访问B组件</button><component :is="currentComponent" v-if="currentComponent"></component></div>
</template><script setup>
import { shallowRef, defineAsyncComponent  } from 'vue'
const currentComponent = shallowRef(null)const loadComponent = (name) => {currentComponent.value = defineAsyncComponent(() => import(`./components/${name}.vue`))
}
</script><style lang="scss" scoped>
button {margin-right: 10px;
}
</style>

在这里插入图片描述

经过改动后,现在只有点击了按钮,才会 import 对应的组件,从而减少了初始加载的时间,实现了懒加载的特性。

2. 使用细节

2.1 注册方式

2.1.1 全局注册

与普通组件一样,异步组件可以使用 app.component() 全局注册。示例代码:

app.component('MyComponent', defineAsyncComponent(() =>import('./components/MyComponent.vue')
))

在这里插入图片描述
完整示例如下:
main.js

import { createApp, defineAsyncComponent} from 'vue'
import App from './App.vue'
import router from './router'const app = createApp(App)app.component('A', defineAsyncComponent(() =>import('@/components/A.vue')
))app.component('B', defineAsyncComponent(() =>import('@/components/B.vue')
))app.use(router)app.mount('#app')

App.vue

<template><div id="app"><button @click="loadComponent('A')">访问A组件</button><button @click="loadComponent('B')">访问B组件</button><component :is="currentComponent" v-if="currentComponent"></component></div>
</template><script setup>
import { shallowRef  } from 'vue'
const currentComponent = shallowRef(null)const loadComponent = (name) => {currentComponent.value = name
}
</script><style lang="scss" scoped>
button {margin-right: 10px;
}
</style>

2.1.2 局部注册(通常配合 is 和 v-if 进行使用)

也可以直接在父组件中直接定义它们:

<template><div id="app"><C /></div>
</template><script setup>
import { defineAsyncComponent  } from 'vue'const C = defineAsyncComponent(() =>import('@/components/C.vue')
)
</script><style lang="scss" scoped>
button {margin-right: 10px;
}
</style>

不过,我们通常不会直接在组件中使用 <C /> 进行使用,因为异步组件的目的,就是为了需要时加载,所以通常会配合
<component :is="currentComponent" v-if="currentComponent">
这样的语句进行使用,可参考 1.2.2 异步组件 的使用示例。

2.2 加载与错误状态(delay 和 timeout 无效)

defineAsyncComponent() 也支持在高级选项中处理加载和错误状态:

const AsyncComp = defineAsyncComponent({// 加载函数loader: () => import('./Foo.vue'),// 加载异步组件时使用的组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间,默认为 200msdelay: 200,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 3000
})

下面,让我们来看一个完整示例。
App.vue:

<template><div id="app"><button @click="loadComponent('A')">访问A组件</button><button @click="loadComponent('D')">访问D组件</button><component :is="currentComponent" v-if="currentComponent"></component></div>
</template><script setup>
import { shallowRef, defineAsyncComponent } from 'vue'
import LoadingComponent from '@/components/LoadingComponent.vue'
import ErrorComponent from '@/components/ErrorComponent.vue'
const currentComponent = shallowRef(null)const loadComponent = (name) => {currentComponent.value = defineAsyncComponent({// 加载函数loader: () => import(`@/components/${name}.vue`),// 加载异步组件时使用的组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间,默认为 200msdelay: 3000,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 3000})
}</script><style lang="scss" scoped>
button {margin-right: 10px;
}
</style>

A.vue:

<template><div>这是A组件</div>
</template><script setup></script><style lang="scss" scoped></style>

LoadingComponent.vue:

<template><div>假装我在loading...</div>
</template><script setup></script><style lang="scss" scoped></style>

ErrorComponent.vue:

<template><div>这是加载失败后展示的组件</div>
</template><script setup></script><style lang="scss" scoped></style>

D.vue 未创建。

按理说,如果我点击 “访问A组件” 按钮,会有 3s 中的时间显示加载组件,然后在切换到A组件。但是实际上,却马上切换到了A组件。
在这里插入图片描述
按理说,点击D组件,应该也会经历 3s 的延迟后,再显示错误组件。但是实际上却马上显示了报错组件。
在这里插入图片描述

这可能需要搭配 <Suspense> 组件才会生效,让我们届时在进行进一步的学习。


上一章 《Vue3 重构待办事项(主要练习组件化)》

http://www.dtcms.com/a/554714.html

相关文章:

  • 如何做电影网站才不侵权贵州省省建设厅网站
  • osgearth\AFsim如何加载影像瓦片数据和高程数据
  • 是做网站设计好还是杂志美编好有没有傻瓜式建设网站
  • Derby - Derby 服务器(Derby 概述、Derby 服务器下载与启动、Derby 连接数据库与创建数据表、Derby 数据库操作)
  • 慈溪高端网站设计甘肃嘉峪关建设局网站
  • 重庆渝云建设有限公司官方网站深圳网站运营
  • 【开题答辩实录分享】以《自动售货机刷脸支付系统的设计与实现》为例进行答辩实录分享
  • 瑜伽 网站模板夏津网站建设电话
  • 长沙手机网站设计公司网站建设与客户价格谈判技巧
  • 网页抓包实战,工具选型、分层排查与真机取证流程
  • 荆门市城乡建设管理局网站广州建设工程中心网站
  • 可以自己建设购物网站家具营销策划方案
  • 基于阿里云效实现cicd记录
  • 网站结构的规划与设计拓者设计吧首页
  • 递归专题4 - 网格DFS与回溯
  • 免费排版网站专业网站是什么意思
  • 精准且快速校准的语音神经假体研究与学习
  • 授权购买网站广州越秀网站制作
  • 马克·扎克伯格大学做的网站lnmp wordpress 500
  • Maven 入门指南
  • 网站建设电话销售技巧和话术合肥网络seo
  • 湖北人工智能建站系统软件360建筑兼职网官网
  • 怎么搭建自己的电影网站建设部网站社保联网
  • 学习笔记二:发展历程
  • 回森AI智能服务唯一服务已更新
  • 设计的素材网站有哪些软件平台开发流程
  • 山东网站建设优化技术网站建设的实践体会
  • 免费设计软件网站攻击Wordpress网站
  • Nginx简介与应用场景:从原理到实战案例
  • 网站的icp备案信息企业网站建设流程第一步是什么