轮播组件swiper设置属性loop:true时的必经之路

7,167 阅读3分钟

弱小和无知不是生存的障碍,傲慢才是。 ----《三体》

  • 在维护且一直看不惯的项目终于在UI改版之际申请了重构。终于可以按照自己的构思写,一切都如此地美好。上线前,甲方爸爸要求首页的轮播图要加循环。然后,就碰到了这个问题~
  • 先简单介绍下项目,这是一个ToB的项目(4s店使用,汽车相关)。轮播不仅仅有图片,每个轮播中还要展示车辆的相关数据以及可点击的按钮。

根据swipe介绍,当设置loop参数为true时,会在原本的slide前后复制若干个slide。

项目中的轮播组件其实是15个,但是element渲染出的是17个,根据上图中的标注就可以看出,当从最后一个轮播滑动到第一个后,其实页面渲染的是组件自行复制出的slide(也就是途中的第17个),反之同理。(你品,你细品!) 有意思的事情来了,这个时候你去点击你以为的第一个轮播(其实是组件自己复制出的最后一个轮播),点击是无效的。

解决loop为true时页面渲染和点击问题

  • 在程序运行中涉及到页面中一些dom的刷新操作,使用swiper提供的一些接口进行监听并不能实时对组件复制出的头尾两个slide进行实时刷新。百般无果,最后用了最粗暴的方式去解决。直接js更改首尾虚拟slide的dom样式
  • 点击事件之前是直接在dom上绑定的click事件,loop为true后,多出的两个slide上的点击事件无效。此时,用swiper组件中的onclick做点击数事件的处理。此时,就要知道点击的是轮播中的那哪一个。
  • 欢迎大家在评论区留下更加优雅的方式

废话不多说,上代码

<template>
    <div  class="swiper-container" id="detail">
        <div class="swiper-wrapper">
            <div class="swiper-slide" v-for="(item,index) in list" :key="index">
                <button :class="[item.available?'available':'']">开始</button>
            </div>
        </div>
    </div>
</template>
<script>
    export default{
        data(){
            return {
                lastDom: null,
                firstDom: null,
                mySwiper:null,
                initSlide:0
            }
        },
        created(){
            this.firstDom = document.getElementsByClassName("swiper-slide-duplicate")[0];
            this.lastDom = document.getElementsByClassName("swiper-slide-duplicate")[1];
        },
        watch:{
            //在你需要的地方将这两个slide中的一些dom样式进行更改
            //百试不得其解后用了这种办法,希望有大神路过给出优解
            "availableList.length":{
                handler(newValue,oldValue){
                    //添加样式
                    this.lastDom.classList.add("available");
                    this.firstDom.classList.add("available");
                }
            }
        },
        mounted(){
            let _this = this
            _this.$nextTick(()=>{
                _this.mySwiper = new Swiper("#detail",{
                    direction: "vertical",
                    initialSlide: _this.initSlide,
                    loop: true,
                    on:{
                        slideChangeTransitionEnd: function() {
                             _this.initSlide = this.realIndex;
                        },
                        //对于习惯用箭头函数的小伙伴,这里有个小坑。箭头函数中的this其实是上级作用于中的this。这当我们想取函数汇总的realIndex或者activeIndex时,老老实实用function定义函数,此时函数中的this指向的是swiper实例。
                        click: function(el) {
                            //判断点击的dom是否是button
                            if (
                                el.target.className.includes("available")
                            ) {
                               _this.toConfig(this);
                            }
                        },
                    }
                })
            })
        },
        methods:{
            toConfig(vm){
                let index =vm.clickedIndex - vm.activeIndex + vm.realIndex === this.list.length+2? 0: vm.clickedIndex - vm.activeIndex +vm.realIndex;
                //然后就可以做你想做的事情了
            }
        }
        
    }
    //以上
</script>

以上