# 1. 背景
在普通的Vue项目中,图片懒加载使用的 vue-lazyload (opens new window) 这个三方库,用法如下:
Vue.use(VueLazyload, {
preLoad: 1.3,
error: errorimage,
loading: loadimage,
attempt: 1
})
然后在Vue模板中,这样来使用:
<ul>
<li v-for="img in list">
<img v-lazy="img.src" >
</li>
</ul>
到了uni-app小程序项目中,是无法支持的,因为目前uni-app并不支持自定义指令,所以要想其他办法改造懒加载。
# 2. 方案
翻了一下网上的小程序懒加载方法,有以下几种:
- 小程序自带的lazy-load属性
- onPageScroll监听页面滚动,计算图片高度和clientHeight的关系来判断
- 用wx.createIntersectionObserver().relativeToViewport等API,监听图片是否在当前视口
后两种方法不适合我们的场景,如果是单个页面还可以,要做通用方法的话,要改造很多代码。
并且关键是lazy-load是有效果的,可以尝试在img上加个@load方法,然后滚动下,可以看到是有懒加载的。
<img :src="url" lazy-load @load="loadImg">
现在问题变成了如何批量替换之前的v-lazy,让它在小程序模式下,变成lazy-load,且转为src。这个可以用webpack-loader解决,如果匹配到v-lazy的img标签,将其替换成对应的src,并添加lazy-load属性。
此外,之前的懒加载是可以自动获取元素的宽高,然后请求指定宽高的数据,来达到性能优化的目的。到了小程序,这一步不能自动获取了,想了个方法,可以把size/width/height写在标签属性上,然后调用自定义的压缩方法,获取指定宽高的url。
这个urlHandler可以写在全局mixin中,方法里添加云图片的压缩参数。
总体的思路如下:
<img v-lazy="img">
<!-- 会转为 -->
<img :src="img">
如果提供 options.urlHandler,则用 urlHandler 包裹,比如:
<img v-lazy="img">
<!-- 会转为 -->
<img :src="getCompressUrl(img)">
如果提供 size 和 urlHandler,则向 urlHandler 传递 size 参数,比如:
<img v-lazy="img" size="50">
<!-- 会转为 -->
<img :src="getCompressUrl(img, 50, 50)">
以下几种size都是有效的:
<img v-lazy="src" size="50">
<img v-lazy="src" data-size="50">
<img v-lazy="src" width="50" height="100">
<img v-lazy="src" data-width="50" data-height="100">