遇到大量数据渲染swiper组件内容时,如果一次性渲染所有数据,会造成大量DOM渲染影响渲染性能,同时,如果渲染后用户并没有滑动到具体swiper-item,也造成多余DOM渲染。为此,有没有什么方案可以优化上述两种缺陷?答案是,有的!通过动态swiper-item渲染实现(虚拟swiper)。
思路
核心
基于循环轮播特性(circular=true),用最少的SwiperItem实现无限左右滑动。
实现
- 默认渲染一个SwiperItem子集,只有3个数据项,记录当前屏幕展示的SwiperItem的顺序
current以及对应的数据索引index - 监听左右滑动事件(
swiper-change事件),获取新的SwiperItem的顺序新current以及对应的数据索引新index - 根据最新的数据索引(
index)获取前一个数据项(index-1)和下一个数据项(index+1)构造新的SwiperItem子集([index-1, index, index+1]) - 为了维持当前屏幕展示的SwiperItem(
current)与新的SwiperItem子集中的顺序(ind),需要对新的SwiperItem子集进行顺序调整,根据滑动方向进行对应的左移/右移/不移动 - 重复第2步
图示
当前屏幕渲染 [3, 4, 5] 3个SwiperIte(子集),当前屏幕展示的SwiperItem=4,对应Swiper顺序current=1,对应数据索引index=3
向右移动一次(Swiper左滑)
当前屏幕展示的SwiperItem=5,对应Swiper顺序current=2,对应数据索引index=4
基于当前数据索引index=4 获取新的SwiperItem子集 [4, 5, 6],此时子集中SwiperItem=5在子集中的索引ind=1,而Swiper展示的顺序current=2,因此数据子集需要 向右 移动1位得到 [6, 4, 5]
这里右移1位得到子集
[6, 4, 5],能够保证当前Swiper向左/向右滑动,都能正常衔接上一项或者下一项,因为Swiper是循环的(circular=true)。
如果这里不对子集
[4, 5, 6]进行移动,则需要手动调整Swiper的顺序current=1,才能与之对应,但是由于改变了Swiper的顺序状态,页面会有一次抖动(体验差)
Swiper重新渲染swiper-item为 [6, 4, 5]
swiper-item 通过v-for渲染,需要指定key值,减少多余渲染。
继续向右移动一次(Swiper左滑)
当前屏幕展示的SwiperItem=6,对应Swiper顺序current=0,对应数据索引index=5
基于当前数据索引index=5 获取新的SwiperItem子集 [5, 6, 7],此时子集中SwiperItem=6在子集中的索引ind=1,而Swiper展示的顺序current=0,因此数据子集需要 向右 移动2位(或者向左移动1位)得到 [6, 7, 5]
Swiper重新渲染swiper-item为 [6, 7, 5]
继续向右移动一次(Swiper左滑)
当前屏幕展示的SwiperItem=7,对应Swiper顺序current=1,对应数据索引index=6
基于当前数据索引index=6 获取新的SwiperItem子集 [6, 7, 8],此时子集中SwiperItem=7在子集中的索引ind=1,而Swiper展示的顺序current=1,因此数据子集不需要移动。
Swiper重新渲染swiper-item为 [6, 7, 8]
其他操作如上