资讯专栏INFORMATION COLUMN

那些年,那些坑--swiper loop:true引发绑定dom的click事件无效及解决方案

Barrior / 2599人阅读

摘要:第一版这是最常规的做法,把事件绑定在上。阻止点击事件冒泡世界杯揭幕战超新星球助攻俄罗斯沙特格里兹曼宣布留马竞颜值满分世界杯首日美女球迷盘点盘点历届世界杯大比分屠杀希望借此可以帮助遇到此问题的小伙伴,祝大家的生活中再无。

对于 swiper,只要做过轮播图的童鞋应该都再熟悉不过了。这是一个很强大的图片轮播插件,本身无任何第三方库依赖,即插即用。api 文档很清晰,所以很快能够上手。但是,再好的插件也会出现令人不愉快的地方,当然,今天所讨论的并不是插件本身的问题,只是开发者是按照常规做法去使用,而恰好此时出现了令人费解的问题。

现象

在使用 swiper 这个库的时候,一旦设置 loop:true 的时候,会遇到 dom 绑定事件无法触发的问题。

环境

● vuejs 2.5.16
● swiper 4.3.3
● vue-awesome-swiper 3.1.3

采坑

下面来说说我是怎么一步一步采坑并最终解决这个问题的。这里只贴出关键性的代码片段。

第一版

这是最常规的做法,把 click 事件绑定在 dom 上。但有两点不足之处:

click 点击事件有时候无任何反应,并且这种情况必现

点击下面的 title,并不能触发 click 事件,因为并没有绑定

html 代码

js 代码

new Vue({
  el: "#app",
  data: function () {
    return {
      swiperOption: {     // 轮播配置
        width: window.innerWidth,
        autoplay: {
          delay: 3000
        },
        loop: true,   // 循环滚动
        pagination: {   // 分页器
          el: ".swiper-pagination"
        },
        preventLinksPropagation: false   // 阻止点击事件冒泡
      },
      bannerList: [
        {
          id: "1",
          title: "世界杯揭幕战-超新星1球2助攻俄罗斯5-0沙特 格里兹曼宣布留马竞",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/AYes-hcyszrz3457297.jpg"
        },
        {
          id: "2",
          title: "颜值满分!世界杯首日美女球迷盘点",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/H3Wz-hcyszrz4804003.jpg"
        },
        {
          id: "3",
          title: "盘点历届世界杯大比分“屠杀”",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/FNuk-hcyszrz4805039.jpg"
        }
      ]
    }
  },
  methods: {
    // 坑在这里:
    // 会发现有的时候,click 事件点击无反应,而且这种情况是必现的
    handleClickSlide(index) {
      console.log("handleClickSlide current index", index);
    }
  }
});
改良的第二版

解决了上述两个问题,但同时也存在以下几个问题

常用的 activeIndex (用来标识当前点击的第几张图片),但控制台输出的值是错乱的

左右作切换的时候,activeIndex 的值也是错乱的

html 代码

js 代码

new Vue({
  el: "#app",
  data: function () {
    return {
      swiperOption: {     // 轮播配置
        width: window.innerWidth,
        autoplay: {
          delay: 3000
        },
        loop: true,   // 循环滚动
        pagination: {   // 分页器
          el: ".swiper-pagination"
        },
        preventLinksPropagation: false   // 阻止点击事件冒泡
      },
      bannerList: [
        {
          id: "1",
          title: "世界杯揭幕战-超新星1球2助攻俄罗斯5-0沙特 格里兹曼宣布留马竞",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/AYes-hcyszrz3457297.jpg"
        },
        {
          id: "2",
          title: "颜值满分!世界杯首日美女球迷盘点",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/H3Wz-hcyszrz4804003.jpg"
        },
        {
          id: "3",
          title: "盘点历届世界杯大比分“屠杀”",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/FNuk-hcyszrz4805039.jpg"
        }
      ]
    }
  },
  computed: {
    swiper() {
      return this.$refs.mySwiper.swiper;
    }
  },
  methods: {
    // 坑在这里
    // 一开始点击第一张图片,控制台输出的 activeIndex 竟然是 1,难道不应该是 0吗?
    // 并且一个循环之后,点击第一张图片, 控制台输出的 activeIndex 竟然变成了 4。。。
    handleClickSlide() {
      // 这个应该是最为想到一个属性,用来标识当前点击图片的索引
      const {activeIndex} = this.swiper && this.swiper;
      console.log("handleClickSlide current index", activeIndex);
    }
  }
});
最终版

通过 swiper 强大的 api 文档,解决了上述出现的几个问题。关键点在于:当 loop 设置为 true 的时候,不能再用 activeIndex 或者 clickedIndex。只能用 realIndex。官方的解释为:当前活动块的索引,与 activeIndex 不同的是,在 loop 模式下不会将复制的块的数量计算在内。
点击事件不能绑定在 dom
不过稍不注意,也会出现新的坑(代码里有指出)

html代码

js 代码

let vm = null;
new Vue({
  el: "#app",
  data: function () {
    return {
      swiperOption: {     // 轮播配置
        width: window.innerWidth,
        autoplay: {
          delay: 3000
        },
        loop: true,   // 循环滚动
        pagination: {   // 分页器
          el: ".swiper-pagination"
        },
        on: {
          click: function () {
            // 这里有坑
            // 需要注意的是:this 指向的是 swpier 实例,而不是当前的 vue, 因此借助 vm,来调用 methods 里的方法 
            // console.log(this); // -> Swiper
            // 当前活动块的索引,与activeIndex不同的是,在loop模式下不会将 复制的块 的数量计算在内。           
            const realIndex = this.realIndex;
            vm.handleClickSlide(realIndex); 
          }
        },
        preventLinksPropagation: false   // 阻止点击事件冒泡
      },
      bannerList: [
        {
          id: "1",
          title: "世界杯揭幕战-超新星1球2助攻俄罗斯5-0沙特 格里兹曼宣布留马竞",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/AYes-hcyszrz3457297.jpg"
        },
        {
          id: "2",
          title: "颜值满分!世界杯首日美女球迷盘点",
          imgUrl: "http://n.sinaimg.cn/sports/180/w640h340/20180615/H3Wz-hcyszrz4804003.jpg"
        },
        {
          id: "3",
          title: "盘点历届世界杯大比分“屠杀”",
          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);
    }
  }
});

希望借此可以帮助遇到此问题的小伙伴,祝大家的生活中再无 bug。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95548.html

相关文章

  • FastClick 源码解读

    摘要:所有浏览器浏览器不支持安卓中中有属性安卓中中有属性有属性的有属性的所以在不需要的浏览器会直接掉,不会执行下面的所有代码。见源码行,可以看出在响应无操作后,则触发。 其实一直就想花些时间读一读那些优秀的开源库,今天终于下了决定打算死磕下自己,2016年每个月读2-3个优秀的开源库,把源码精彩的地方和自己心得分享给大家。 目录 (一)背景(二)源码解析(三)Zepto 点击穿透与 Fast...

    Chaz 评论0 收藏0
  • 那些,前端学习之路疑难杂症(四):面试中遇到3个问题概览

    摘要:闭包能用来实现私有化和创建工厂函数等作用。关于闭包的常见面试题是这样的写一个函数,循环一个整数数组,延迟秒打印这个数组中每个元素的索引。 文章来源:http://mp.weixin.qq.com/s/vs0... 前言 在公众号上看到了这篇文章,觉得很有用,有助于理解JS学习中的一些重点难点。决定把它整理下发布出来。该文章主要介绍了JS中的三个问题。在以后的几篇文章里,我会详细介绍这三...

    gecko23 评论0 收藏0
  • 又被事件冒泡了一把,这次要彻底弄懂浏览器事件

    摘要:事件冒泡一个简单,但是坑了我无数回的知识点与的交互通过事件来实现。而浏览器的事件流是一个非常重要的概念。不去讨论那些古老的浏览器有事件捕获与事件冒泡的争议,只需要知道在中规定的事件流包括了三个部分,事件捕获阶段处于目标阶段事件冒泡阶段。 打算封装一个弹窗组件,做的时候忘记了考虑事件冒泡的因素,结果被坑得不要不要的。为了解决自己的问题,去查阅了不少资料,把事件流相关的知识都给总结一下。 ...

    Ocean 评论0 收藏0
  • 又被事件冒泡了一把,这次要彻底弄懂浏览器事件

    摘要:事件冒泡一个简单,但是坑了我无数回的知识点与的交互通过事件来实现。而浏览器的事件流是一个非常重要的概念。不去讨论那些古老的浏览器有事件捕获与事件冒泡的争议,只需要知道在中规定的事件流包括了三个部分,事件捕获阶段处于目标阶段事件冒泡阶段。 打算封装一个弹窗组件,做的时候忘记了考虑事件冒泡的因素,结果被坑得不要不要的。为了解决自己的问题,去查阅了不少资料,把事件流相关的知识都给总结一下。 ...

    TIGERB 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<