在开发项目时,遇到了需要实现在轮播模式下(loop:true)点击元素事件的需求,在多次踩坑后,总结记录到这篇文章中,希望对遇到这个问题的同行有所帮助。

        注:代码使用vue-awesome-swiper开发,而vue-awesome-swiper也是将swiper进行封装,二者遇到的问题、解决思路一致,只是写法上略有不同。因此下文将vue-awesome-swiper、swiper统称为swiper。

        出现点击失效的原因:在loop模式下,超出实际数量的轮播项实际上是被复制出来的,是swiper虚拟slide进行填充,对这些虚拟slide元素进行操作无效。

        解决思路:1.将需要获取的参数通过html属性的方式传递给swiper包裹的子元素。

                          2.使用swiper的事件监听api,获取当前的dom。

                          3.获取到html自定义属性。

代码如下:

<template>
  <div class="swiper-box">
    <swiper :options="mySwiperOption">
      <swiper-slide  v-for="(item, index) in dataList" :key="index">
        <div class="card" :data-card="JSON.stringify(item)">
          <span>姓名:{{ item.name }}</span>
        </div>
      </swiper-slide>
    </swiper>
  </div>
</template>
<script>
import 'swiper/dist/css/swiper.css'
import { swiper, swiperSlide } from 'vue-awesome-swiper'

export default {
  data() {
    return {
      mySwiperOption: {
        pagination: {
          el: '.swiper-pagination', //与slot="pagination"处 class 一致
          clickable: true, //轮播按钮支持点击
        },
        //自动播放
        autoplay: {
          delay: 5000,
          disableOnInteraction: false
        },
        //循环
        loop:true,
        on: {
          click: (e) =>  {
            this.handleClickCard(e)
          }
        }
      },
      dataList: [{
        name: '张三'
      }, {
        name: '李四'
      }]
    }
  },
  components: {
    swiper,
    swiperSlide
  },
  methods: {
    handleClickCard(e) {
      let cardDataJSON = e.target.getAttribute('data-card')
      console.log(e.target.dataset.card, e.target.getAttribute('data-card'))
      let cardData = JSON.parse(cardDataJSON)
      console.log(cardData)
    }
  }
}
</script>
<style lang="scss" scoped>
.swiper-box {
  width: 238px;
  height: 100px;
}
.card {
  width: 238px;
  height: 100px;
  background: #d3d3d3;
}
</style>

        使用html自定义属性传值时,属性必须要data-开头,在data-之后必须要有字符串,且因为大小写会失效,所以多单词时建议用“-”连接。

        获取html参数时可以通过dataset或者getAttribute,如代码中日志,两种方式获取的参数是一样的。

       注意自定义属性传递后的数据结构会默认使用toString()方法,因此Object格式需要转为JSON格式再传递,Array格式在传递后需要使用split转为数组,Number也需要在传递后再转为Number,如以下例子:

<div class="card"
    :data-str="'张三'"
    :data-idx="123"
    :data-list="[1,2,3]"
    :data-obj="{name: '张三'}"
>
    <span>姓名:{{ item.name }}</span>
</div>

handleClickCard(e) {
    let cardData = e.target.dataset
    console.log(
        cardData.str,
        cardData.idx,
        cardData.list,
        cardData.obj
    )
}

打印出的结果分别问:

 

Logo

前往低代码交流专区

更多推荐