lazy-load 在多数场景下失效,需用 uni.createintersectionobserver 主动控制;创建 observer 必须在 onready/mounted 后、观察真实 dom 节点、设兼容 threshold、及时 disconnect;图片需预设高度或预加载,避免布局抖动与重复请求。

lazy-load 属性在多数场景下不生效,尤其在 scroll-view 里、安卓 WebView 中、H5 默认配置下基本失效。真要优化图片加载性能,必须绕过它,用 uni.createIntersectionObserver 主动控制。
为什么 lazy-load 经常白配
它不是“开了就跑”,而是平台级限制叠加行为不一致:
- 微信小程序只对页面级滚动(
onPageScroll)响应,scroll-view是自定义容器,lazy-load完全不监听 - H5 端默认关闭,需手动启用
IntersectionObserver或加decode="async",但兼容性仍差 - 安卓 WebView 下,
lazy-load是 JS 滚动监听模拟的,主线程压力大,反而更卡 - 无法设预加载距离(比如提前 200px 加载),触发时机不可控,常导致滑动时白屏或跳帧
uni.createIntersectionObserver 怎么写才不翻车
不是调 API 就完事,漏掉任一环节就会白屏、重复加载或静默失败:
- 必须在
onReady或mounted后创建 observer,不能放created或data里——此时this.$refs还是空的 - 观察目标必须是真实 DOM 节点:
observer.observe(this.$refs.imgRef),不能传字符串选择器(如'.img-item')指望自动查 - 动态列表中,
observe必须等this.$nextTick()后再执行,否则节点未渲染完成 -
threshold参数跨端不兼容:小程序只认数组(如[0, 0.1]),H5 支持数字(如0.05);设错会静默失败,图片永远不加载 - 每次
observe后记得调observer.disconnect(),否则内存泄漏
图片高度不确定?布局抖动就躲不掉
没预设高度 = 渲染后重排 = 滚动跳动 + 触发多次 observe + 用户感知卡顿:
- 最优解是服务端返回宽高字段,前端直接设:
:style="{ height: item.height + 'px' }" - 做不到就用
uni.getImageInfo预加载——比new Image()可靠,后者在安卓 WebView 里不触发解码 - 绝对不要用
v-if控制显隐,组件销毁重建会导致src重赋值、重复请求;改用:style="{ opacity: loaded ? 1 : 0 }"+ CSS transition - 如果用 uView 的
u-lazy-load,注意:img-mode不是widthFix时,height必须设为固定值(如300rpx),auto或100%会导致图片不显示
安卓加载慢?懒加载可能雪上加霜
根本原因是 <image></image> 在安卓 WebView 下走的是 JS + Canvas 渲染链路,不是原生控件:
- 优先用
.nvue页面 + manifest.json 开启"nvueStyle": true,让<image></image>走原生渲染路径 - 预加载关键图必须用
uni.preloadImage,别用new Image()——前者触发原生层解码,后者只是下载完扔缓存 - 避免
mode="aspectFill"或scaleToFill,这些模式安卓下无硬件加速,纯 CPU 裁剪 - 图片本身得先压缩:CDN 加参数裁剪(如
?x-oss-process=image/resize,w_200/format,webp),或本地走resizeImg(url, 200)工具函数
最易被忽略的一点:所有懒加载逻辑都依赖“真实节点存在”和“高度可预测”。没占位、没预加载、没断开 observer,性能优化就只是把问题从网络层转移到了渲染层。











