如何用Vue3 Suspense组件实现异步图片加载?
解决Vue3 Suspense配合图片异步加载+骨架屏的问题
你判断的核心问题没错:当前代码无法正常工作是因为async setup()里没有返回Suspense需要等待的Promise,而直接请求图片URL触发CORS是因为跨域图片加载需要正确配置跨域属性。下面是简便且有效的实现方案:
核心思路
通过创建原生Image对象,监听其加载/错误状态,将图片加载过程包装为Promise,让Suspense等待这个Promise完成后再渲染真实图片,同时规避CORS问题。
完整的AsyncImageLoader组件实现
<template> <img :src="imageUrl" alt="Profile Photo" style="filter: invert(0); clip-path: circle(38%)" /> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "AsyncImageLoader", props: { imageUrl: { type: String, required: true, }, }, async setup(props) { // 将图片加载过程包装为Promise,供Suspense等待 await new Promise((resolve, reject) => { const img = new Image(); // 配置跨域属性,解决跨域图片加载的CORS问题 img.crossOrigin = "anonymous"; img.onload = () => resolve(null); img.onerror = (err) => reject(err); img.src = props.imageUrl; }); }, }); </script>
关键细节说明
- Suspense等待逻辑:
async setup()中的await会让Suspense持续显示fallback骨架屏,直到图片加载完成的Promise被resolve。 - CORS问题解决:给Image对象设置
crossOrigin = "anonymous",同时要确保图片所在服务器的响应头包含Access-Control-Allow-Origin(允许你的站点域名访问),即可避免跨域错误。 - 错误处理:如果需要处理图片加载失败的场景,可以在
onerror回调中添加错误提示或降级逻辑,比如reject后在组件内捕获错误做对应处理。
父组件代码无需修改
你之前使用Suspense的父组件代码是正确的,保持原样即可:
<div class="w-40"> <Suspense> <AsyncImageLoader :image-url="photoUrl" /> <template #fallback> <SkeletonLoader shape="circle" class="mx-7 h-[106px]" /> </template> </Suspense> </div>
这样就能实现图片加载完成前显示骨架屏,加载完成后切换为真实图片的效果,同时解决了CORS和Suspense不等待的问题。
内容的提问来源于stack exchange,提问作者Tyler
相关产品推荐
相关产品推荐

