Swiper is familiar to anyone who has done swiper. This is a very powerful picture rotation plug-in, itself without any third-party library dependence, plug and play. The API documentation is clear, so it’s easy to get started. However, even the best plug-ins can be annoying, and of course, today’s discussion is not about the plug-ins themselves, but the developers are using them in the usual way, and there are inexplicable problems.

The reason:

When using swiper, dom binding events cannot be triggered when loop: True is set.

Environment:

  • Vuejs 2.5.16

  • Swiper 4.3.3

  • Vue – awesome – swiper 3.1.3

Mining pit

Here’s how I solved the problem step by step. Only the key code snippets are posted here.

First edition:

The most common way to do this is to bind the Click event to the DOM. However, there are two disadvantages:

  1. Click events sometimes go unanswered, and they always do
  2. Clicking on the title below does not trigger the click event because there is no binding

The HTML code

<div class="banner" v-if="bannerList.length">
  <swiper :options="swiperOption" ref="mySwiper">
    <swiper-slide
      v-for="(banner, index) in bannerList"
      :key="banner.id"
      @click.native="handleClickSlide(index)">
      <div class="banner-item">
        <img :src="banner.imgUrl" alt="news">
        <p>{{banner.title}}</p>
      </div>
    </swiper-slide>
    <div class="swiper-pagination" slot="pagination"></div>
  </swiper>
</div>Copy the code

Js code

new Vue({
  el: '#app',
  data: function () {
    return{swiperOption: {width: window.innerWidth, autoplay: {delay: 3000}, loop:true, // loop scrolling pagination: {//'.swiper-pagination'
        },
        preventLinksPropagation: false// prevent click events from bubbling}, bannerList: [{id:'1',
          title: 'World Cup opener - Supernova 1 goal 2 assists Russia 5-0 Saudi Griezmann announces his move to Atletico Madrid',
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/AYes-hcyszrz3457297.jpg'
        },
        {
          id: '2',
          title: 'Full marks for appearance level! 'Beautiful women' on World Cup Day,
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/H3Wz-hcyszrz4804003.jpg'
        },
        {
          id: '3',
          title: 'Carnage' in World Cup history,
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/FNuk-hcyszrz4805039.jpg'}]}}, methods: {handleClickSlide(index) {console.log();'handleClickSlide current index', index); }}});Copy the code


Improved second edition:

The above two problems have been solved, but there are also the following problems

  1. The usual activeIndex (used to identify the number of images currently clicked), but the console output is out of order
  2. The activeIndex value is also distorted when toggling left and right

The HTML code

<div class="banner" v-if="bannerList.length">
  <swiper :options="swiperOption" ref="mySwiper" @click.native="handleClickSlide">
    <swiper-slide
      v-for="(banner, index) in bannerList"
      :key="banner.id">
      <div class="banner-item">
        <img :src="banner.imgUrl" alt="news">
        <p>{{banner.title}}</p>
      </div>
    </swiper-slide>
    <div class="swiper-pagination" slot="pagination"></div>
  </swiper>
</div>Copy the code

Js code

new Vue({
  el: '#app',
  data: function () {
    return{swiperOption: {width: window.innerWidth, autoplay: {delay: 3000}, loop:true, // loop scrolling pagination: {//'.swiper-pagination'
        },
        preventLinksPropagation: false// prevent click events from bubbling}, bannerList: [{id:'1',
          title: 'World Cup opener - Supernova 1 goal 2 assists Russia 5-0 Saudi Griezmann announces his move to Atletico Madrid',
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/AYes-hcyszrz3457297.jpg'
        },
        {
          id: '2',
          title: 'Full marks for appearance level! 'Beautiful women' on World Cup Day,
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/H3Wz-hcyszrz4804003.jpg'
        },
        {
          id: '3',
          title: 'Carnage' in World Cup history,
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/FNuk-hcyszrz4805039.jpg'
        }
      ]
    }
  },
  computed: {
    swiper() {
      return this.$refs.mySwiper.swiper; ActiveIndex = 1; activeIndex = 1; activeIndex = 0; // After a loop, click on the first image and the activeIndex output from the console changes to 4...handleClickSlideConst {activeIndex} = this.swiper &&this.swiper; const {activeIndex} = this.swiper &&this.swiper; console.log('handleClickSlide current index', activeIndex); }}});Copy the code

The final version

Swiper’s powerful API documentation addresses several of these issues. The key point is:

  1. whenloopSet totrueCan’t be used againactiveIndexorclickedIndex. Can only useRealIndex.The index of the active block, andactiveIndexThe difference is that in loop mode, noCopy the blockCount the number of.

  2. Click events cannot be bound todom on

However, if you are not careful, new pits can appear (as indicated in the code).

The HTML code

<div class="banner" v-if="bannerList.length">
  <swiper :options="swiperOption" ref="mySwiper">
    <swiper-slide
      v-for="(banner, index) in bannerList"
      :key="banner.id">
      <div class="banner-item">
        <img :src="banner.imgUrl" alt="news">
        <p>{{banner.title}}</p>
      </div>
    </swiper-slide>
    <div class="swiper-pagination" slot="pagination"></div>
  </swiper>
</div>Copy the code

Js code

let vm = null;
new Vue({
  el: '#app',
  data: function () {
    return{swiperOption: {width: window.innerWidth, autoplay: {delay: 3000}, loop:true, // loop scrolling pagination: {//'.swiper-pagination'
        },
        on: {
          click: function() {// There is a pit // Note that this refers to the swpier instance, not the current vue, so use vm to call methods // console.log(this); // Swiper -> Swiper // Index of active blocks. Unlike activeIndex, the number of copied blocks is not counted in loop mode. const realIndex = this.realIndex; vm.handleClickSlide(realIndex); } }, preventLinksPropagation:false// prevent click events from bubbling}, bannerList: [{id:'1',
          title: 'World Cup opener - Supernova 1 goal 2 assists Russia 5-0 Saudi Griezmann announces his move to Atletico Madrid',
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/AYes-hcyszrz3457297.jpg'
        },
        {
          id: '2',
          title: 'Full marks for appearance level! 'Beautiful women' on World Cup Day,
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/H3Wz-hcyszrz4804003.jpg'
        },
        {
          id: '3',
          title: 'Carnage' in World Cup history,
          imgUrl: 'http://n.sinaimg.cn/sports/180/w640h340/20180615/FNuk-hcyszrz4805039.jpg'
        }
      ]
    }
  },
  computed: {
    swiper() {
      return this.$refs.mySwiper.swiper; }},created() {
    vm = this;
  },
  methods: {
    handleClickSlide(index) {
      console.log('handleClickSlide current index', index); }}});Copy the code

Hope this can help encountered this problem small partners, I wish you no more bugs in life.