事情是这样的,我做了一个在线壁纸小程序,壁纸预览部分为了更好时使用体验,增加了类似于那些短视频上滑下滑快速切换壁纸预览的功能,为了避免重复造轮子直接使用了 swiper 来时实现滑动快速切换壁纸。
问题所在
当壁纸量比较多的时候,全部渲染成 swiper-item,会出现明显性能问题。还有个原因应该预览壁纸时加载的都是高清原图,直接全部加载出来,对性能也是很大一个浪费。图片的加可以通过设置 lazy-load 懒加载图片。
解决方案
解决方案也挺简单,直接使用分页去处理,比如有 200 项,但是我们一次只渲染 3 个 swiper-item,比如当前下标是 1(对应原列表下标1),当你下滑时新的下标就是 2(对应原列表下标2)了,这个时候就需要我们更新下标 0(对应原列表下标3),为当前项,对应原始列表中的下一个,上滑也是这样的逻辑,这样就保证每次滑洞都按照原始列表顺序显示的,但是实际页面只渲染 3 个 swiper-item,和虚拟列表原理类似。
官方提供了一个 video-swiper 组件,原理时类似的,只不过是给视频列表使用的,我们参考他的实现进行修改。
实现
假设我们的数据的为 list,实际渲染的数据为 swiperList,我们现在给他就固定 3 个 swiper-item,前后滑动的时候去替换数据,正向滑动的时候去替换滑动后的下一个数据,反向滑动的时候去替换滑动后的上一个数据,然后将 swiper 设置为可衔接滑动,这样保证一直可以循环滑动,然后更具滑动方向替换数据。
监听 swiper 的 bindchange 事件,可以获取到滑动后的 current,然后在 bindchange 事件里更新数据
滑动的方向判断
// swiper 长度 |
获取 swiperList 需要更新的下标
let updateIndex; |
除了需要 swiperList 更新下标,还得记录对应 list 的下标
// 获取当前项对应 list 下标 |
然后据可以根据滑块方向和 previewIndex,就可以确定更新 swiperList 数据了
this.setData({ |
根据上面思路基本上可以解决 swiper 数据量大性能问题了,但是还存在一些问题。
- 滑块边界问题,list 数据也是有限的,也会滑到边界,需要对边界做一个判断处理
这个问题可以根据 previewIndex 下标去判断是否到达了边界,如果不需要无限加载数据,可以在达到边界时直接回弹静止滑块继续滚动,因为设置 swiper 为衔接滑动,达到边界时滑动时上一个或者下一个还是会显示有其他 swiper-item,所有需要我们添加一个空的 swiper-item 用来占位。如果时需要无限加载数据,可以在快到达边界时提前拉取数据,等拿到数据时继续下滑,否则反弹回去保持在最后一个。
- 当 previewIndex 不是通过滑块更新时候,比如直接从 0 跳到 5 会有默认滚动动画,导致体验很差
这个解决方式是在非滑动更新时候,先将动画时间 duration 设置为 0 ,去掉动画,然后在更新下标和恢复动画。
this.setData({ duration: 0 }, () => { |
代码实现
相对完整的代码实现
<swiper vertical="{{true}}" duration="{{duration}}" current="{{swiperIndex}}" circular="{{circular}}" bindchange="handleChangeBigImage"> |
// swiper 长度 |
我很可爱,请给我钱
- 本文链接: https://www.imalun.com/wx_swiper/
- 版权声明: 本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。