相较于web端或者H5开发,小程序本身在性能上弱很多(但用户体验上要好)。以前开发时服务器性能过剩在那里帮你撑着脸面,你对自己的代码质量和编程习惯心里没数,小程序就是一面镜子。
废话少说,要解决的问题是,小程序加载图片闪烁,渐渐出现,出现的很慢等等效果不尽人意的体验。
如果你的小程序本身只用加载很少的图片,那么其实问题不大。如果是像购物APP那样或者是一款有图片列表的应用,那么以下方案肯定能帮到你。
1.从源头把控,所有的图片放到云存储上(或者用小程序开发工具的素材管理),后台对图片进行可接受范围内的最大限度压缩,图片宽高不用太大,大概预留你图片容器的1.5倍就行了,除非你做图片放大镜功能,否则小程序上加载2倍图意义不大,反正图片也不可以被长按,被放大。
2.官方文档上写着图片image上自带lazy-load(懒加载),默认是关闭的,你把它开启,但是要记得它只在两个固定容器(page或scroll-view)下才有用。
以上方案针对下滑加载更多列表的应用,类似下图这个,是有一定效果的:
3.做完上述两步,如果你发现就算你一屏就加载4张图片,每张才30k以内还是一张一张的闪现,尤其在安卓上(嘿嘿,你以为安卓会一直输下去?),但是下滑加载更多时下面的图片显示体验却意外顺滑(官方的lazy-load生效了),那么就继续看。
就算首屏就加载四张小图,图片还没有全都刷的一下出来那种顺畅体验(看看美团外卖小程序那顺畅,带劲)。
那么我们就做一个整体加载,我们把图片列表装在一个容器里,把容器的透明度设置为0,当我们请求接口并判断图片加载完成之后,我们再让容器渐显。这时候效果就是四张图片全部刷的出来了,看下面示例图(tab切换时更新了列表数据):
一个思路完善但代码简要的例子:
wxml上根据showList来控制加载时显示动画,完成显示容器;
<!-- loading动画 -->
<block wx:if="{{!showList}}">
<view class='list-loading'>
<image src='loading.gif'></image>
</view>
</block>
<!-- 列表容器 -->
<block hidden="{{!showList}}">
<scroll-view class='contents fade_in}}'>
<navigator wx:for="{{itemList}}" wx:key="item.id" url="{{../specialist/index}}">
<image lazy-load="true" class='list-img' src="{{item.img}}"></image>
</navigator>
</scroll-view>
</block>
js里控制showList的变化;
Page({
data:{
itemList:[],
showList:false
},
//切换tab时,
switchTab(){
//加载loading动画
this.setData({
showList:false
});
},
//获取新tab下的列表
getListItem(){
//...请求接口拿到了新数据的数组:newList,赋值
this.setData({
itemList:newList
});
//让图片加载会,都完事了,再让图片容器整体显示出来吧,所以给个定时器争取下时间
//250的时间怎么来的?我说是感觉你会不会打死我。如果你的容器显示出来的时候图片还是闪烁加载
//那么再延长点时间,自己改改感受感受你就知道妙不可言了。
setTimeout(()=>{
this.setData({
showList:true
});
},250);
//微信最近提供了兼容性极低的nextTick方法可以代替setTimeout,也许能解决时间全靠估的问题。
//但是我不用,ok?
}
})
在wxss里,写个渐显的动画过渡效果,在列表容器显示时过渡一下,圆润些。
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
以上思路能解决在切换tab或者是大量请求图片时的图片加载体验,如果你不是像我这样接手的时候代码已经被写好了并且限定你在短时间内做完优化,那么我建议大量图片的时候采用预加载,提前把后面的图片先加载好,不要做这种tab切换时重新替换数据源的事情,要不得。
如果,我是说如果啊,当你做完这些优化之后,在一些低端安卓机上你的延迟时间需要开到800ms才能保证容器的整体加载,那么我最后想说的方案,也是我这次优化直接把体验评分最差D的小程序搞到最棒A的老科技webp。
webp是什么,懒得讲,自己百度。15k的jpg能给你压缩到1k(原图越小压缩效率越高,原图越大压缩效率越低),webp有兼容问题,只在chrome系的浏览器或者webview里面能正常工作,也就是说,只有安卓手机的小程序能用webp格式的照片,在ios上是显示不出来的。
解决方案自然而然的就出来了,根据系统类型判断该加载什么格式的图片,方便起见,在小程序启动时,设置好全局变量,以便在各个模块使用。代码实现如下:
App({
globalData: {
ios: false
},
//判断机型
onLaunch: function() {
var vm = this;
var phoneInfo = wx.getSystemInfo({
success: function(res) {
if (res.system.indexOf("iOS") != -1) {
vm.globalData.ios = true
}
}
});
}
})
这样,在获取列表之后,根据全局变量ios的值来给列表图片赋值相应的路径,iOS系统使用常规的jpg,png等,android则使用webp格式
完成最后这一步,你会发现现在局势反过来了,android上的图片加载速度秒杀iOS,就算你iOS性能好又怎样,还不是败给chrome的webp,嘿嘿,又有谁能想到呢。
纵观网上的所谓的图片加载的解决方案,当我亲身使用之后还是发现不尽人意,差点都拿不出手这个小程序,直到我想到了这么个方法,用过的都说牛逼,领导一开心,也不抓我做事了,所以我才有时间写下这篇博客,帮助后来人。