直接用uni.previewimage+flex布局即可实现九宫格图片预览,无需自研手势逻辑;但必须满足三个硬条件:图片地址为完整url、current必须是urls数组中严格相等的字符串、九宫格容器使用flex-wrap而非grid。

直接用 uni.previewImage + flex 布局就能实现,不用自己写 canvas 或手势逻辑,但必须满足三个硬条件:图片地址是完整 URL、current 必须是 urls 数组里存在的字符串、九宫格容器得用 flex-wrap 而不是 grid。
uni.previewImage 传参为什么总失败
常见静默失败(控制台无报错)基本都卡在这几个点:
-
current传了数组索引(如0)或空字符串,它只认和urls中某一项**完全相等的字符串**,大小写、斜杠方向都不能差 -
urls里混入了null、undefined或本地临时路径(如tempFilePaths[0]),H5 端只认带协议的网络图(https://开头) - 小程序真机上路径区分大小写,
file:///xxx/IMG_001.jpg和file:///xxx/IMG_001.JPG被视为两张不同图 - 没做校验就直接传
tempFilePaths,页面跳转后临时路径失效,预览白屏
实操建议:点击图片时取 item.src(即 urls[index]),别传 index;调用前先 urls.filter(Boolean) 清空假值。
九宫格布局为什么在小程序里错行或溢出
根本原因是 display: grid 在微信小程序基础库低于 2.17.0 时不可用,且部分安卓机即使支持也会塌陷。Flex 是唯一跨端稳的方案。
- 容器必须设
display: flex; flex-wrap: wrap;,漏掉flex-wrap就会单行挤成一条缝 - 子项宽度别用
flex: 1,要用flex: 0 0 calc(33.33% - 4px)(减去间隙),iOS 微信里flex: 1容易错行 - 间隙统一用
margin,别用gap(H5 兼容性差);也别用padding隔开格子,否则总宽超 100% 触发换行异常 - 每张图外层
view设box-sizing: border-box,避免border或padding破坏等分
图片变形、留白、加载闪烁怎么根治
核心是控制宽高比 + 加载行为,不是单纯调 mode。
-
mode="aspectFill"是九宫格首选,但前提是图片外层view有固定宽高比——用padding-bottom: 33.33%比设height更可靠,避免图片加载完成触发重排 - 禁用
mode="scaleToFill",人像或文字图会明显拉伸失真 - H5 端图片加载慢?给
image加lazy-load无效(H5 不支持),改用uni.$on('imageLoad')控制加载态 - 真机滚动时图片反复重绘?确保父容器宽高固定,
image的width和height都设为100%,别依赖内容撑开
不足 9 张时最后一行为啥还占满宽度
Flex 默认把剩余项平均分配到整行,视觉上像“缺图但留空位”。微博实际做法是左对齐、不撑满,靠的是数据驱动而非 CSS。
- 别用空
view占位——小程序里空节点仍参与 flex 计算,会导致错位 - 正确做法:v-for 渲染真实数量,比如
v-for="(item, i) in pics" :key="i",不要补足到 9 个 - 如果 UI 要求必须显示 9 个格子(比如加号按钮在第九位),用
v-for="(item, i) in [...pics, ...Array(9 - pics.length).fill(null)]",再用v-if="item"控制image渲染 - 超出 9 张?直接截断,用
+N文字盖在第九张图上,朋友圈原生逻辑就是如此
真正容易被忽略的点是:H5 端所有临时路径都无效,uni.chooseImage 返回的 tempFilePaths 在 H5 必须走 canvas 压缩转 base64 或上传后取返回的 CDN 地址,才能传给 uni.previewImage。











