图片预览前先 filter 掉空地址:一个容易忽略的细节

33 阅读3分钟

一、业务背景

在小程序里,我们常会做「列表里有多张图,点击某一张进入大图预览、支持左右滑动看其他张」的需求。例如:

  • 证件正页 / 副页各占一项,每项有一张图;
  • 商品有多张主图、详情图,点任意一张进预览并滑动;
  • 订单/售后里多张凭证图,点开全屏查看。

实现方式一般是:从列表里收集所有图片地址,组成一个 urls 数组,再调用 uni.previewImage({ urls, current }),用 current 表示当前点击的那张。很多人会写出类似逻辑:

previewImage(index) {
  const urls = this.list.map((item) => item.imageUrl);
  uni.previewImage({
    urls,
    current: urls[index] || urls[0],
  });
}

问题在于:列表里的 imageUrl 并不保证每项都有值。一旦出现空字符串或 null,就容易踩坑。


二、为什么会有「空地址」?

接口和前端写法,很容易产出空值,例如:

  • 接口只返回了部分图:比如只返回了「正页」图,「副页」没图,前端用 value.backImgUrl || '' 兜底,副页的 imageUrl 就是 ''
  • 可选字段:列表里某些项本身是可选的,没数据时 imageUrl''nullundefined
  • 加载中/失败:先渲染列表骨架,图还没拿到时先赋空,后续再补。

所以 map 之后得到的往往是「带空位的数组」,例如:

['https://cdn.example.com/a.jpg', '', 'https://cdn.example.com/c.jpg']

若直接把这样的数组交给 uni.previewImage,就可能出现:预览报错、白屏、或某一张是「破图」,体验很差。而且 current 若正好是 '',部分端上会直接异常。


三、实现思路:map 取地址,filter 去空

思路很简单:先 map 出所有 imageUrl,再用 filter 把空地址去掉,只把「有效链接」交给预览接口。

示例(类名、变量名均为示意,与具体业务解耦):

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,
  });
}

要点:

  1. map:从列表中取出每一项的图片地址,得到「地址数组」。
  2. filter((url) => url):去掉所有假值(''nullundefined),只保留非空字符串,保证 urls 里全是有效链接。
  3. if (urls.length === 0) return:没有一张有效图时,不调用预览,避免无意义的调用或报错。
  4. current 的取值:在「已过滤」的 urls 里用 currentIndex 取当前项;若索引越界(例如过滤后长度变了),用 urls[0] 兜底。

这样,无论接口返回几张图、列表里有多少项是空图,预览时只会看到「有地址」的那几张,且 current 一定是有效 URL,行为更稳定。


四、filter 在这里的具体作用(重点)

很多人只想到「用 map 把地址拿出来」,容易忽略「拿出来的数组里可能有空元素」。filter 的作用就是把这层风险在调用预览前处理掉。

不做 filter做了 filter
urls 里可能含 ''nullundefinedurls 里只有非空字符串
current 可能正好是空,导致预览异常current 一定在有效列表中,不会传空
预览可能报错、白屏或某张图裂开只预览有效图,体验更可控

为什么用 filter((url) => url)

  • 利用 JavaScript 的「假值」判断:''nullundefined0false 在布尔上下文中为 false,(url) => url 等价于「只保留为 true 的项」,即去掉空字符串和 null/undefined。
  • 若业务上还要排除「格式明显不对」的地址,可以再在 filter 里加一层判断(例如正则或 url.startsWith('http')),但多数场景下「去空」已经能避免大部分问题。

小结一句:map 负责「从列表里取出地址」,filter 负责「只保留有效地址」;两者配合,再配合 urls.length === 0 的判断,预览逻辑就更严谨,这也是很多人容易忽略的一步。


五、小结

  • 业务场景:列表多图点击预览,urls 来自列表项的 imageUrl,接口或前端兜底会导致部分项为空。
  • 实现思路map 取地址 → filter 去空 → 判空再调 uni.previewImagecurrent 在过滤后的数组里取。
  • 重点:filter 在此处的作用是「保证传给预览接口的只有有效 URL」,避免空地址导致的报错或异常展示,是值得写进习惯的一个小细节。