Vue2 结合 swiper 实现无限翻页效果

918 阅读1分钟

一、前言

在一次迭代开发中,有个业务场景需要实现滑动查看的效果,于是我就想到使用 swiper 来进行开发,但是在实现之后发现,当页面中的数据量大的时候,滑动效果变得越加卡顿。于是我查看了 swiper 中对于虚拟Slide功能的描述,但苦于目前市面上没有可参考的使用 Vue2 的做法,最后我看到了 renderSlide 的使用方法,实现出了无限翻页滚动的效果

二、安装依赖

由于目前在项目中使用的是 Vue2.x 的版本,所以本次我们的我们是基于 vue2 安装的 swiper 版本,另外关于 swiper 的使用这里就不再赘述,不熟悉的可以参考官网查看 => www.swiper.com.cn/api/index.h…

# 指定版本安装,不要问为啥不用最新的 4.x,问就是有坑

yarn add swiper@^4.0.7 vue-awesome-swiper@^3.1.3

三、使用

紧接着在项目中引入

// main.js
import Vue from 'vue';
import VueAwesomeSwiper from 'vue-awesome-swiper';
import 'swiper/dist/css/swiper.css';

Vue.use(VueAwesomeSwiper /* { default options with global component } */);

这样你就可以使用了,下面展示结合 Vue 组件的用法,下方方法 handleRender 中我们重新实例化组件对象,并且将 router、store 作为子组件实例的参数传入,防止在子组件内使用 this.routerthis.router 或 this.store 的时候出现上下文对象执行异常。

<template>
  <div class="wrapper">
    <swiper ref="mySwiper" :options="swiperOptions" style="width: 100%;height: 100%"></swiper>
  </div>
</template>
<script>
import Vue from 'vue';
import SlideDetail from './slide-detail.vue';

export default {
  data() {
    return {
      swiperOptions: {
        virtual: {
          slides: [],
          renderSlide: this.handleRender,
        },
      },
      dataSource: [],
      activeIndex: 100,
    };
  },
  computed: {
    swiper() {
      return this.$refs.mySwiper?.swiper;
    },
  },
  mounted() {
    this.dataSource = Array(3000)
        .fill('slide')
        .map((item, index) => {
          return {
            id: index,
            name: `${item}_index`,
          };
        });
    // 默认激活展示
    this.initSwiper(0);
  },
  beforeDestroy() {
    this.swiper && this.swiper.destroy();
  },
  methods: {
    initSwiper(activeIndex) {
      if (!this.swiper || !this.swiper.virtual) {
        return;
      }
      console.log(' ==> this.activeIndex', activeIndex);
      this.swiper.virtual.removeAllSlides(); // 移除全部
      this.swiper.virtual.appendSlide(this.dataSource); // 插入Slide 数组
      this.swiper.slideTo(activeIndex, 0, false);
    },
    handleRender(slide, index) {
      let SlideInstance = Vue.extend(SlideDetail);
      const slideVm = new SlideInstance({
        store: this.$store, // 添加 store 对象,防止上下文获取异常
        router: this.$router, // 添加 router 对象,防止上下文获取异常
        propsData: {
          id: this.dataSource[index] ? this.dataSource[index].id : null,
          name: this.dataSource[index] ? this.dataSource[index].name : null,
        },
      }).$mount();

      return slideVm.$el;
    },
  },
};
</script>

<style lang="scss" scoped>
.wrapper {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
</style>

下面我们新增一个子组件,需要注意的是,子组件的类名一定要存在 swiper-slide,不然会导致样式错乱

<template>
  <div class="swiper-slide">
    {{ `当前 id 为:${id};name 为 ${name}` }}
  </div>
</template>

<script>
export default {
  name: "SlideDetail",
  props: {
    id: {
      type: Number,
      default: null
    },
    name: {
      type: String,
      default: ""
    }
  }
}
</script>

以上我们就实现了在 Vue2 下结合 swiper 的虚拟列表,对于大量数据渲染的性能问题就能很好解决了。