uni-app 实现虚拟swiper,避免一次性渲染所有swiper-item引起DOM爆炸

551 阅读3分钟

遇到大量数据渲染swiper组件内容时,如果一次性渲染所有数据,会造成大量DOM渲染影响渲染性能,同时,如果渲染后用户并没有滑动到具体swiper-item,也造成多余DOM渲染。为此,有没有什么方案可以优化上述两种缺陷?答案是,有的!通过动态swiper-item渲染实现(虚拟swiper)。

思路

核心

基于循环轮播特性(circular=true),用最少的SwiperItem实现无限左右滑动。

实现

  1. 默认渲染一个SwiperItem子集,只有3个数据项,记录当前屏幕展示的SwiperItem的顺序current以及对应的数据索引index
  2. 监听左右滑动事件(swiper-change事件),获取新的SwiperItem的顺序新current以及对应的数据索引新index
  3. 根据最新的数据索引(index)获取前一个数据项(index-1)和下一个数据项(index+1)构造新的SwiperItem子集([index-1, index, index+1])
  4. 为了维持当前屏幕展示的SwiperItem(current)与新的SwiperItem子集中的顺序(ind),需要对新的SwiperItem子集进行顺序调整,根据滑动方向进行对应的 左移/右移/不移动
  5. 重复第2步

图示

当前屏幕渲染 [3, 4, 5] 3个SwiperIte(子集),当前屏幕展示的SwiperItem=4,对应Swiper顺序current=1,对应数据索引index=3

image.png

向右移动一次(Swiper左滑)

当前屏幕展示的SwiperItem=5,对应Swiper顺序current=2,对应数据索引index=4

image.png

基于当前数据索引index=4 获取新的SwiperItem子集 [4, 5, 6],此时子集中SwiperItem=5在子集中的索引ind=1,而Swiper展示的顺序current=2,因此数据子集需要 向右 移动1位得到 [6, 4, 5]

image.png

这里右移1位得到子集[6, 4, 5],能够保证当前Swiper向左/向右滑动,都能正常衔接上一项或者下一项,因为Swiper是循环的(circular=true)。

如果这里不对子集[4, 5, 6]进行移动,则需要手动调整Swiper的顺序current=1,才能与之对应,但是由于改变了Swiper的顺序状态,页面会有一次抖动(体验差)

Swiper重新渲染swiper-item为 [6, 4, 5]

image.png

swiper-item 通过v-for渲染,需要指定key值,减少多余渲染。

继续向右移动一次(Swiper左滑)

当前屏幕展示的SwiperItem=6,对应Swiper顺序current=0,对应数据索引index=5

image.png

基于当前数据索引index=5 获取新的SwiperItem子集 [5, 6, 7],此时子集中SwiperItem=6在子集中的索引ind=1,而Swiper展示的顺序current=0,因此数据子集需要 向右 移动2位(或者向左移动1位)得到 [6, 7, 5]

image.png

Swiper重新渲染swiper-item为 [6, 7, 5]

image.png

继续向右移动一次(Swiper左滑)

当前屏幕展示的SwiperItem=7,对应Swiper顺序current=1,对应数据索引index=6

image.png

基于当前数据索引index=6 获取新的SwiperItem子集 [6, 7, 8],此时子集中SwiperItem=7在子集中的索引ind=1,而Swiper展示的顺序current=1,因此数据子集不需要移动。

image.png

Swiper重新渲染swiper-item为 [6, 7, 8]

image.png

其他操作如上

uni-app 插件

传送门

如果觉得对您有帮助,请小编瑞一下

IMG_2654.JPG