对于某些组件来说,我们并不希望一开始全部加载,而是需要的时候进行加载;这样的做得目的可以很好的提高用户体验。为了实现这个功能,Vue3中为我们提供了一个方法,即defineAsyncComponent,这个方法可以传递两种类型的参数,分别是函数类型和对象类型,接下来我们分别学习
defineAsyncComponent方法接收一个工厂函数是它的基本用法,这个工厂函数必须返回一个Promise,Promise的resolve应该返回一个组件,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <template> <logo-img /> <hello-world msg="Welcome to Your Vue.js App" /> </template> <script setup> import { defineAsyncComponent } from 'vue' import LogoImg from './components/LogoImg.vue' // 简单用法 const HelloWorld = defineAsyncComponent(() => import('./components/HelloWorld.vue'), ) </script> |
当然,仅仅如此页面我们是无法体会到异步效果,让我们延迟加载下试试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | const time = (t, callback = () => {}) => { return new Promise(resolve => { setTimeout(() => { callback() resolve() }, t) }) } const HelloWorld = defineAsyncComponent(() => { return new Promise((resolve, reject) => { ;(async function () { try { await time(2000) // 延迟两秒加载再加载HelloWorld组件 const res = await import('./components/HelloWorld.vue') resolve(res) } catch (error) { reject(error) } })() }) }) |
defineAsyncComponent方法也可以接收一个对象作为参数,该对象中有如下几个参数:
如下代码展示defineAsyncComponent方法的对象类型参数的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <template> <logo-img /> <hello-world msg="Welcome to Your Vue.js App" /> </template> <script setup> import { defineAsyncComponent } from 'vue' import LogoImg from './components/LogoImg.vue' import LoadingComponent from './components/loading.vue' import ErrorComponent from './components/error.vue' // 定义一个耗时执行的函数,t 表示延迟的时间, callback 表示需要执行的函数,可选 const time = (t, callback = () => {}) => { return new Promise(resolve => { setTimeout(() => { callback() resolve() }, t) }) } // 记录加载次数 let count = 0 const HelloWorld = defineAsyncComponent({ // 工厂函数 loader: () => { return new Promise((resolve, reject) => { ;(async function () { await time(300) const res = await import('./components/HelloWorld.vue') if (++count < 3) { // 前两次加载手动设置加载失败 reject(res) } else { // 大于3次成功 resolve(res) } })() }) }, loadingComponent: LoadingComponent, errorComponent: ErrorComponent, delay: 0, timeout: 1000, suspensible: false, onError(error, retry, fail, attempts) { // 注意,retry/fail 就像 promise 的 resolve/reject 一样: // 必须调用其中一个才能继续错误处理。 if (attempts < 3) { // 请求发生错误时重试,最多可尝试 3 次 console.log(attempts) retry() } else { fail() } }, }) </script> |
上面的代码中,我们加载组件时前两次会请求错误,只有第三次加载才会成功
现实项目开发中,我们可能更希望于当用户滚动屏幕时候,当组件在屏幕可视区范围内进行异步懒加载,这个时候我们可以通过插件vueuse轻松完成,当然,vueuse不仅仅只是做这个,它内置封装了很多开发过程中我们所需要的功能,这只是冰山一角,让我们一起来体会下该插件的强大
组件按需引入:当用户访问到了组件再去加载该组件, IntersectionObserver检测目标元素的可见性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <template> <div ref='target'> <C v-if='targetIsVisible'></C> </div> </template> <script setup> import { useIntersectionObserver } from '@vueuse/core' const C = defineAsyncComponent(() => import('../components/C.vue') ) const target = ref(null); const targetIsVisible = ref(false); const { stop } = useIntersectionObserver( target, ([{ isIntersecting }]) => { if( isIntersecting ) { targetIsVisible.value = isIntersecting }else{ // 你还可以在适当时机去停止监听 stop() } }, ) </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <Suspense> <template #default> <A></A> </template> <template #fallback> 加载中... </template> </Suspense> <script setup> const A = defineAsyncComponent(() => import('../components/A.vue') ) </script> |
npm run build打包完成后,异步组件有单独的js文件,是从主体js分包出来的
1 2 | A.c7d21c1a.js C.91709cb2.js |
上一篇:Pinia如何让数据持久化存储?
下一篇:HTML5事件—visibilitychange页面可见性事件监听
支付宝扫一扫打赏
微信扫一扫打赏
共 0 条评论关于"Vue3中defineAsyncComponent异步组件-可视区范围内懒加载"
最新评论