一、业务背景
在小程序里,我们常会做「列表里有多张图,点击某一张进入大图预览、支持左右滑动看其他张」的需求。例如:
- 证件正页 / 副页各占一项,每项有一张图;
- 商品有多张主图、详情图,点任意一张进预览并滑动;
- 订单/售后里多张凭证图,点开全屏查看。
实现方式一般是:从列表里收集所有图片地址,组成一个 urls 数组,再调用 uni.previewImage({ urls, current }),用 current 表示当前点击的那张。很多人会写出类似逻辑:
js
previewImage(index) {
const urls = this.list.map((item) => item.imageUrl);
uni.previewImage({
urls,
current: urls[index] || urls[0],
});
}
问题在于:列表里的 imageUrl 并不保证每项都有值。一旦出现空字符串或 null,就容易踩坑。
二、为什么会有「空地址」?
接口和前端写法,很容易产出空值,例如:
- 接口只返回了部分图 :比如只返回了「正页」图,「副页」没图,前端用
value.backImgUrl || ''兜底,副页的imageUrl就是''。 - 可选字段 :列表里某些项本身是可选的,没数据时
imageUrl为''、null或undefined。 - 加载中/失败:先渲染列表骨架,图还没拿到时先赋空,后续再补。
所以 map 之后得到的往往是「带空位的数组」,例如:
js
['https://cdn.example.com/a.jpg', '', 'https://cdn.example.com/c.jpg']
若直接把这样的数组交给 uni.previewImage,就可能出现:预览报错、白屏、或某一张是「破图」,体验很差。而且 current 若正好是 '',部分端上会直接异常。
三、实现思路:map 取地址,filter 去空
思路很简单:先 map 出所有 imageUrl,再用 filter 把空地址去掉,只把「有效链接」交给预览接口。
示例(类名、变量名均为示意,与具体业务解耦):
js
previewImage(currentIndex) {
const urls = this.docList
.map((item) => item.imageUrl)
.filter((url) => url);
if (urls.length === 0) return;
const current = urls[currentIndex] ?? urls[0];
uni.previewImage({
urls,
current,
});
}
要点:
- map:从列表中取出每一项的图片地址,得到「地址数组」。
- filter((url) => url) :去掉所有假值(
''、null、undefined),只保留非空字符串,保证urls里全是有效链接。 - if (urls.length === 0) return:没有一张有效图时,不调用预览,避免无意义的调用或报错。
- current 的取值 :在「已过滤」的
urls里用currentIndex取当前项;若索引越界(例如过滤后长度变了),用urls[0]兜底。
这样,无论接口返回几张图、列表里有多少项是空图,预览时只会看到「有地址」的那几张,且 current 一定是有效 URL,行为更稳定。
四、filter 在这里的具体作用(重点)
很多人只想到「用 map 把地址拿出来」,容易忽略「拿出来的数组里可能有空元素」。filter 的作用就是把这层风险在调用预览前处理掉。
| 不做 filter | 做了 filter |
|---|---|
urls 里可能含 ''、null、undefined |
urls 里只有非空字符串 |
current 可能正好是空,导致预览异常 |
current 一定在有效列表中,不会传空 |
| 预览可能报错、白屏或某张图裂开 | 只预览有效图,体验更可控 |
为什么用 filter((url) => url)?
- 利用 JavaScript 的「假值」判断:
''、null、undefined、0、false在布尔上下文中为 false,(url) => url等价于「只保留为 true 的项」,即去掉空字符串和 null/undefined。 - 若业务上还要排除「格式明显不对」的地址,可以再在 filter 里加一层判断(例如正则或
url.startsWith('http')),但多数场景下「去空」已经能避免大部分问题。
小结一句:map 负责「从列表里取出地址」,filter 负责「只保留有效地址」;两者配合,再配合 urls.length === 0 的判断,预览逻辑就更严谨,这也是很多人容易忽略的一步。
五、小结
- 业务场景 :列表多图点击预览,
urls来自列表项的imageUrl,接口或前端兜底会导致部分项为空。 - 实现思路 :
map取地址 →filter去空 → 判空再调uni.previewImage,current在过滤后的数组里取。 - 重点:filter 在此处的作用是「保证传给预览接口的只有有效 URL」,避免空地址导致的报错或异常展示,是值得写进习惯的一个小细节。