本文分享一下之前同事对项目的一个优化点,很小很细节。

我们途虎的电商项目中,前端会涉及到大大小小很多的图片,跟淘宝京东一样,商品有一个列表,点击进去是一个商品详情页面,一张商品大图占据了屏幕的半壁江山,本文的主体就是这张大图。

做 Android 的时候,图片就是一个固定的 url,对图片的压缩缓存处理都是基于 Android 系统的,系统有这样的机制我们只要把原始图片保存到本地,用的时候根据宽高压缩处理显示就可以,事实上,第三方图片加载库都是基于这一原理,所以基本不会出现要讲的问题,即列表图片加载好了,点击进去的列表放大图加载很慢。即使图片很大渲染慢也可以设置一张本地默认图片来友好提示。

然而,在前端小程序页面中,如果列表图片与详情图片用同一个 url,那么列表就会加载很慢,因为每个条目的图片都很大,用户体验非常不好。对于这个问题,我司很早就采用了第三方的七牛云,在图片的 url 后面以指定格式加上指定的宽高,就可以只加载相应大小的图片。这样,列表的 url 后面拼上一串宽高,进入详情的时候,采用原始的 url,完美解决!

不知道你们猜出来细节没有,详情页的图片是一张大图,因为平常都是在 WiFi 下测试,而且图片有 cdn 缓存,几乎都是一瞬间就出来了,然而在 4G 的情况下,列表进去其实有一短暂的空白,然后图片才渲染出来,网络差的情况下更不谈了,半屏空白,你说什么滋味?有人说,加载大图时可以用一张默认图片提示,但是在小程序里,项目空间大小很有限,所以所有的图片都走网络,即使使用默认图片也得去加载。

同事参考了京东购物的小程序,发现并没有空白间隙,反复点了好几次,原来,京东是把列表的图片 url 传递到详情了,一开始详情图片会有点模糊,但很快等大图加载完,就变清晰了,整个过程不仔细看,几乎是无感的,所以,途虎项目参考京东,完成了这样一个只有几毫秒空白的优化。

具体到技术的实现细节,image 标签有一个 bindload 方法,此方法是图片加载完成时的一个回调,我们就可以在详情的布局中加入一个宽高为 0 的透明的 image 标签,用它来监听大图加载完成,然后将列表传过来的图片替换掉。

一般详情页,都会有很多张大图,也就是一个图片数组,处理方式也是一样,判断数组的第一张图片与列表的图片是否一样,如果一致,则采用加载回调的这种方式来显示。为了在项目里对调用者友好,会将这个图片加载封装成一个模块,也可以自建一个 npm 私有仓库,后面有再多的项目,都可以享受之前抽象封装优化过的成果。

最后,多说一句,让精益求精成为我们追求的一种做事态度。