@load 是 uni-app 中判断图片加载完成的唯一可靠跨平台信号,@error 是加载失败的唯一捕获入口,二者必须配合使用才能确保图片加载状态准确可控。

@load 事件能准确判断图片加载完成
uni-app 的 组件原生支持 @load,只要图片 HTTP 响应成功、解码完成、渲染就绪,该事件就会触发 —— 这是唯一可靠且跨平台一致的加载完成信号。
常见错误现象:用 v-if 控制 src 切换后监听 @load 却没触发;或在 H5 端用 onload 回调( 才有),结果无响应。
-
@load只对有效,在 uni-app 中不推荐使用,尤其 App 端无法触发原生渲染 - 事件对象
event.detail包含width和height(单位 px),可用于动态适配容器 - 若图片 404 或 CORS 失败,
@load不会触发,必须配合@error捕获异常 - 小程序平台下,
@load触发时机略晚于 DOM 渲染完成,但早于用户可见帧,适合做 loading 关闭或占位图替换
@error 是加载失败的唯一捕获入口
当图片 URL 无效、CDN 返回 404、HTTPS 混合内容被拦截、或路径拼写错误时,@error 会同步触发,而 @load 完全静默 —— 忽略它,就会出现空白/默认缺失图标,造成视觉断裂。
使用场景:头像加载失败显示默认灰色头像、商品图挂了 fallback 到占位图、列表中某张图异常时不中断整体渲染。
-
@error的event.detail.errMsg在不同平台返回值不同:App 端多为 "Failed to load image",微信小程序可能是 "loadImage:fail",不能依赖字符串做精确判断 - 不要在
@error里直接重试src,容易引发无限循环;建议设 flag 防重复,或换备用地址(如/static/fallback.png) - 如果用了 placeholder,
@error触发时 placeholder 仍保留,需手动切换:this.imgLoaded = false; this.fallbackSrc = '/static/error.png'
uni.preloadImage 不提供加载状态回调
uni.preloadImage 是预加载 API,但它不返回 Promise,也不支持 success/fail 回调 —— 它只管“发起预加载”,成败完全黑盒。你无法靠它判断某张图是否已就绪。
常见错误现象:调用 uni.preloadImage 后立刻渲染 ,结果首屏仍闪白;或试图用 setTimeout 等几秒再展示,实际网络快慢差异大,不可靠。
- 预加载效果只能通过后续
@load是否快速触发来间接验证 - 仅限静态完整 URL(如
'https://cdn.com/a.jpg'),拼接变量(如'https://cdn.com/' + id + '.jpg')会静默失效 - 预加载资源数建议 ≤5 张,过多会阻塞 JS 主线程,反而拖慢首屏
IntersectionObserver 不等于图片加载完成
用 IntersectionObserver 监听元素进入视口,只是“开始加载”的起点,不是“加载完毕”。很多开发者误以为 observe 回调里赋值 src 就等于图已就绪,结果滚动时大量图片同时请求、解码、渲染,卡顿明显。
真实链路是:进入视口 → 设置 src → 浏览器发起请求 → 下载 → 解码 → 触发 @load。
- 务必在
@load里才标记“加载完成”,比如item.loaded = true,而不是在 observer 回调里 - observer 的
thresholds: [0.1]可提前触发加载,但不能替代@load做状态判断 - App 端需确认基础库 ≥ 2.6.10,旧版本
uni.createIntersectionObserver可能返回null或行为异常
实际中最容易被忽略的点是:把“开始加载”和“加载完成”混为一谈。哪怕用了预加载、懒加载、占位图,最终呈现是否稳定,只取决于 @load 和 @error 是否被正确监听与响应。











