uni.previewimage 实现九宫格晒图需严格校验 url 合法性、用 flex 布局替代 grid、每图包 view 并设 overflow:hidden、mode 固定为 "aspectfill"、点击前过滤空值并确保 current 匹配有效 url。

直接用 uni.previewImage 就能实现,但必须传合法完整 URL 数组、current 值严格匹配其中一项,否则真机黑屏或静默失败。
九宫格布局本身别碰 grid
微信小程序基础库低于 2.17.0 时 display: grid 直接不识别;H5 端 gap 在 iOS Safari 和安卓 Chrome 表现不一致,间隙错位。朋友圈/美团晒图这种高频展示场景,必须用 flex:
-
flex-wrap: wrap显式声明,漏掉就会所有图片挤在一行溢出容器 - 子项用
flex: 0 0 calc(33.333% - 2 * 8rpx),比单纯width: 33.333%更准——显式扣掉左右 padding,避免box-sizing失效导致总宽超 100% - 图片必须包一层
<view></view>并设overflow: hidden,否则 App 端<image></image>不响应 height,等比裁剪失效 - 每张图的
mode固定用"aspectFill",配合服务端已裁剪的正方形图 URL,禁用"scaleToFill"(拉伸)和"aspectFit"(留白破坏网格)
点击预览前必须校验图片路径
真机上 uni.previewImage 黑屏、卡死、报错 previewImage:fail invalid urls,90% 是因为路径不合法:
- 本地图必须带前缀:
/static/img/xxx.jpg,不能只写xxx.jpg - 网络图必须带协议头:
https://xxx.com/1.jpg,不能是//xxx.com/1.jpg或相对路径 -
urls数组里不能有null、undefined、空字符串,得先过滤:const validUrls = urls.filter(u => typeof u === 'string' && u.trim()) -
current必须是validUrls中存在的字符串,不是索引值——传urls[2],不是2
点击热区小、预览错位、iOS 点透怎么调
晒图是用户主动触发行为,体验细节直接影响信任感:
- 每个图外层
<view></view>加padding: 4rpx扩展点击区域,别只靠图片本身响应 - 图片宽高统一设为
160rpx × 160rpx,太小热区难点,太大在窄屏上换行异常 - iOS 微信里常出现“点一张图却预览另一张”,本质是
v-for渲染未完成就绑了 click,得加@click.stop阻断冒泡,并用this.$nextTick包住uni.previewImage调用 - H5 端注意:rpx 在某些浏览器缩放下会失真,建议对
160rpx做降级:width: 160rpx; width: 100px;
最多 9 张图的边界处理
后端返回 1、5、7 张图很常见,不处理会导致最后一行只剩 1–2 个格子,视觉断裂:
- 补空逻辑写在
computed里:gridList() { const padded = [...this.rawImages]; while (padded.length % 3) padded.push(''); return padded; } - 模板中用
v-if="item"控制是否渲染,避免空字符串生成无效<image></image>标签 - 补的是空字符串或
'',不是null或undefined,否则v-for渲染报错 - 若想保留空白占位(比如维持底部对齐),补
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'这种透明 GIF 占位
最易被忽略的是:App 端大图预览容易 OOM 崩溃,服务端必须对原图做 q=60 压缩再下发;小程序里 uni.previewImage 不支持 WebP,得 fallback 到 JPEG。











