在vue3中使用swiper,自定义分页器

2,408 阅读3分钟

在vue中使用swiper制作轮播图非常简单,但如果想要自定义轮播图下方分页器的样式对于我这种新手来说就没有那么容易啦。下面就把我在网上东拼西凑完成的效果做一个记录。

预期效果

我们以LOl官网的轮播图作为案例,主要做的就是用swiper将轮播图下方的分页器复刻出来。

image.png

具体步骤

  1. 我们使用的是vue3 + swiper7的版本。npm下载swiper这一步就不多说啦。
  2. 在vue引入swiper
//这一行是引入swiper,固定写法
import { Swiper, SwiperSlide } from 'swiper/vue'
//这一行是引入swiper的样式
import 'swiper/css'
//这一行就是固定写法,你的swiper用到什么就在这里写。我们这里只用到了用于控制轮播图播放的Autoplay和分页器Pagination
import SwiperCore, { Autoplay,Pagination } from "swiper"
//这一行也是固定写法,上一行{}里引入的,要在这里再写一下
SwiperCore.use([Autoplay,Pagination])

export default {
//这个是将swiper当做组件,注册一下
components: {
        Swiper,
        SwiperSlide,
    },
}

上面代码中components引入之后,在html代码中就能如下图一样写啦 image.png

3.完成轮播图

export default {
......,
setup{
    //这里写一下轮播图设置,我只写了一个自动播放
    let swiper_options = reactive({
            autoplay: {
                disableOnInteraction: false,
                delay: 3000,
            },
        })
}

然后在swiper的html代码中按如下方式使用

<div class=swiper"> <!--注意swiper外面一定要包这个div,并且在swiper7中类名要写成swiper-->
 <swiper :autoplay="swiper_options.autoplay" :pagination="pagination" @swiper="setControlledSwiper">
 ......
 </swiper>
</div>
  1. 自定义分页器

1、主要代码:

export default {
......,
setup{
    ......,
    //判断是否为轮播图下方的分页器加上选中样式(selected)
        let ifSelect = ref(0)
     //自定义swiper分页器
        const pagination = ref({
        //el是分页器的类名,当然你也可以用这个类名在style中写样式这样就可以自定义分页器样式(这是个小技巧)
            el: ".promo-title-list",
            //此参数设置为true时,点击分页器的指示点分页器会控制Swiper切换。
            clickable: true,
            //这个属性是将分页器样式设置为自定义
            type: 'custom',
            //用于自定义分页器的函数,vue3在这里面写东西很麻烦,我只写了一个让分页器跟随轮播图切换的效果
            renderCustom: function (swiper, current, total) {
                //具体原理我也不太懂,这里只要写上"将当前分页器当前所在span的下标赋值给ifSelected"的逻辑就行啦,至于它是怎么什么时候执行的,怎么将分页器和轮播图连在一起的我就不知道啦。
                ifSelect.value = current - 1
                console.log(current)
            }
        })
}

2、接下来我们还要写一个功能:“鼠标放在分页器上轮播图会切换到图片上”。

首先,我们要定义一个swiper实例

//定义空对象
let controlledSwiper = ref({})
//这个是实例化swiper对象的操作,setControlledSwiper这个函数一定要return出去
const setControlledSwiper = (swiper) => {
    controlledSwiper = swiper
 }
 return{
     setControlledSwiper
 }

有了swiper对象之后就可以使用swiper中的方法啦

这里调用slideTo方法让轮播图跳转到与分页器对应的页,select函数会绑定到分页器的鼠标触碰事件上
function select(index) {
    controlledSwiper.slideTo(index,500,false)
}

将select函数绑定到分页器的鼠标触碰事件上

<span ........ @mousemove="select(index)">.......</span>
  1. 自定义分页器用到的CSS样式
.promo-title-list {
    width: 820px;
    height: 40px;
    overflow: hidden
}

.promo-title-list>span {
    list-style: none;
    float: left;
    width: 164px;
    height: 40px;
    box-sizing: border-box;
    background-color: #e3e2e2;
    font-size: 14px;
    text-align: center;
    line-height: 40px;
    color: #424242;
    letter-spacing: 1px
}
.promo-title-list>span.selected {
    color: #ab8e66;
    background-color: #f7f6f6;
    border-bottom: 2px #cea861 solid
}
  1. 完整代码
<template>
    <div class="m-promo swiper" id="J_promo" exposure-tag="indexScroll,首页轮播" ref="mySwiper">
        <swiper :autoplay="swiper_options.autoplay" :pagination="pagination" @swiper="setControlledSwiper">
            <swiper-slide>
                <a href="https://lol.qq.com/act/a20230616junesummon/index.html?e_code=500130" target="_blank"
                    onclick="PTTSendClick('indexScroll','scroll-22029','命定召唤');">
                    <img t-chan="15282:22029" t-adid="10580665" src="./images/first.jpeg" width="820" height="340"
                        alt="命定召唤 ">
                </a>
            </swiper-slide>
            <swiper-slide>
                <a href="https://lol.qq.com/act/a20230616junesummon/index.html?e_code=500130" target="_blank"
                    onclick="PTTSendClick('indexScroll','scroll-22029','命定召唤');">
                    <img t-chan="15282:22029" t-adid="10580665" src="./images/second.jpeg" width="820" height="340"
                        alt="命定召唤 ">
                </a>
            </swiper-slide>
            <swiper-slide>
                <a href="https://lol.qq.com/act/a20230616junesummon/index.html?e_code=500130" target="_blank"
                    onclick="PTTSendClick('indexScroll','scroll-22029','命定召唤');">
                    <img t-chan="15282:22029" t-adid="10580665" src="./images/third.jpeg" width="820" height="340"
                        alt="命定召唤 ">
                </a>
            </swiper-slide>
            <swiper-slide>
                <a href="https://lol.qq.com/act/a20230616junesummon/index.html?e_code=500130" target="_blank"
                    onclick="PTTSendClick('indexScroll','scroll-22029','命定召唤');">
                    <img t-chan="15282:22029" t-adid="10580665" src="./images/fourth.jpeg" width="820" height="340"
                        alt="命定召唤 ">
                </a>
            </swiper-slide>
            <swiper-slide>
                <a href="https://lol.qq.com/act/a20230616junesummon/index.html?e_code=500130" target="_blank"
                    onclick="PTTSendClick('indexScroll','scroll-22029','命定召唤');">
                    <img t-chan="15282:22029" t-adid="10580665" src="./images/fifth.jpeg" width="820" height="340"
                        alt="命定召唤 ">
                </a>
            </swiper-slide>
        </swiper>
        <!-- <div class="swiper-pagination promo-title-list">
        </div> -->
        <div class="promo-title-list" id="promoTitleList" ref="cur">
            <span class="title" v-for="item, index in list" :key="item" :class="{ selected: ifSelect == index }" style="width: 164px;" @mousemove="select(index)">{{ item }}</span>
            <!-- <span class="title" v-for="item,index in list" :key="item" :data-bannerid="22029" style="width: 164px;">{{ item }}</span> -->
        </div>

    </div>
</template>

<script>
import { ref, nextTick, reactive, onMounted } from 'vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'
import SwiperCore, { Autoplay,Pagination } from "swiper"
SwiperCore.use([Autoplay,Pagination])
export default {
    components: {
        Swiper,
        SwiperSlide,
    },
    setup() {
        //判断是否为轮播图下方的分页器加上选中样式(selected)
        let ifSelect = ref(0)
        //这个是swiper的实例对象
        let controlledSwiper = ref({})
        //该数组用于循环渲染轮播图下方的分页器
        const list = ref([
            "命定召唤", "云顶之弈4周年庆", "山海绘卷", "云顶城邦大战", "冰爽浪花宝典"
        ])

        //这个是实例化swiper对象的操作,setControlledSwiper这个函数一定要return出去
        const setControlledSwiper = (swiper) => {
            controlledSwiper = swiper
        }

        //这里是写轮播图设置的地方,我只写了一个自动播放
        let swiper_options = reactive({
            autoplay: {
                disableOnInteraction: false,
                delay: 3000,
            },
        })

        //自定义swiper分页器
        const pagination = ref({
        //el是分页器的类名,当然你也可以用这个类名在style中写样式这样就可以自定义分页器样式啦(这是个小技巧)
            el: ".promo-title-list",
            //此参数设置为true时,点击分页器的指示点分页器会控制Swiper切换。
            clickable: true,
            //这个属性是将分页器样式设置为自定义
            type: 'custom',
            //用于自定义分页器的函数,vue3在这里面写东西很麻烦,我只写了一个让分页器跟随轮播图切换的效果
            renderCustom: function (swiper, current, total) {
                //具体原理我也不太懂,这里只要写上"将当前分页器当前所在span的下标赋值给ifSelected"的逻辑就行啦,至于它是怎么什么时候执行的,怎么将分页器和轮播图连在一起的我就不知道啦。
                ifSelect.value = current - 1
                console.log(current)
            }
        })
        
        //有了swiper对象之后就可以使用swiper中的方法啦,这里调用slideTo方法让轮播图跳转到与分页器对应的页,select函数会绑定到分页器的鼠标触碰事件上
        function select(index) {
            controlledSwiper.slideTo(index,500,false)
        }
        return {
            ifSelect,
            list,
            swiper_options,
            pagination,
            select,
            setControlledSwiper
        }
    }
}
</script>

<style lang="scss" scoped>
.m-promo {
    float: left;
    width: 820px;
    height: 380px;
    overflow: hidden;
    background-color: #e3e2e2;
    position: relative
}

.promo-img-list {
    width: auto;
    height: 340px;
    overflow: hidden;
    position: relative
}

.promo-img-list>li {
    list-style: none;
    float: left;
    width: 820px;
    height: 340px;
    overflow: hidden
}

.promo-title-list {
    width: 820px;
    height: 40px;
    overflow: hidden
}

.promo-title-list>span {
    list-style: none;
    float: left;
    width: 164px;
    height: 40px;
    box-sizing: border-box;
    background-color: #e3e2e2;
    font-size: 14px;
    text-align: center;
    line-height: 40px;
    color: #424242;
    letter-spacing: 1px
}
.promo-title-list>span.selected {
    color: #ab8e66;
    background-color: #f7f6f6;
    border-bottom: 2px #cea861 solid
}
</style>