项目有个需求是品牌切换,品牌下面的内容(产品信息)跟着切换,然后每个产品信息里面还有轮播图,所以,重点来了,每个品牌下面都有好几个不同的产品,我们要让产品之前的轮播不能起冲突,就要动态设置不同的options(我做项目的时候瞄了一眼官方文档,也查了百度,最后还是自己想办法根据自己的需求去做吧。。。),而且切换品牌的时候要重新处理数据,并且重新渲染该品牌的产品信息(轮播),下面开始吧。
粗略的效果图:
一、基础swiper组件
首先先搞个swiper的简单组件,然后。。重点来了!
下面代码中的1234很明确的标注了出来,因为轮播在产品里面,每个品牌有多个产品,而且有多个品牌,所以相当于两个循环,代码里面可以看到,我已经用随机数设置class想确保每个swiper是独立的,但经过测试发现,同品牌下的产品轮播class都是同一个随机数,所以说循环的时候vue是统一设置好了,所以后面循环的时候我把index加了进去(随机数+index),这样就确保是唯一的了。
最后第5步:
每个被使用到的组件都设置独立的options
最后,watch监听一下传过来的数据,如果你的数据层级多的话一定要用深度监听
<template>
<div class="swiperBox BasisSwiperBox" v-if="imgs.length > 0">
<swiper class="swiper" :options="swiperOption" v-if="isShow">
<swiper-slide v-for="(item,index) in imgs" :key="index">
<img :alt="item.title" :src="item.url">
</swiper-slide>
</swiper>
<!-- 4/修改好的class动态设置到DOM上 -->
<div class="swiper-button-prev" :class="prevClass" slot="button-prev"><i class="el-icon-arrow-left"></i></div>
<div class="swiper-button-next" :class="nextClass" slot="button-next"><i class="el-icon-arrow-right"></i></div>
<div class="swiper-pagination" :class="paginationClass" slot="pagination"></div>
</div>
</template>
<script>
import 'swiper/dist/css/swiper.css'
import { swiper,swiperSlide } from 'vue-awesome-swiper'
export default {
name: 'BasisSwiper',
props: {
imgs: Array,//轮播数据
sIdx: Number//当前轮播index
},
components: {
swiper, swiperSlide
},
created() {
// 1/取一个随机数(切换品牌用不同的随机数),给分页器和前进后退按钮类目后面加上,这是为了防止类名重复,引起不必要的联动
const randomNumber = Math.floor(Math.random() * 1000) + 1;
const paginationClass = 'swiper-pagination' + randomNumber
const prevClass = 'swiper-button-prev' + randomNumber
const nextClass = 'swiper-button-next' + randomNumber
//3/设置属性,把随机数和当前轮播的index加上,确保是唯一的值(随机数+index,确保每个产品的的class不一样)
//(因为产品是多个的,每个产品都有自己的轮播,不加上index的话多个轮播一样用的是同一个随机数,单纯的随机数只能区分切换品牌)
this.paginationClass = paginationClass + this.sIdx
this.prevClass = prevClass + this.sIdx
this.nextClass = nextClass + this.sIdx
},
mounted() {
this.setSwiperOptions()
},
data() {
return {
isShow: false,
paginationClass: '',//2/定义各功能class
prevClass: '',
nextClass: '',
swiperOption: {},//先定义一个空option,后面DOM渲染完后通过方法往里面设置属性
}
},
methods: {
//5/设置swiperOptions,确保这个方法在DOM渲染完后面执行
setSwiperOptions() {
this.swiperOption.pagination = {
el: '.' + this.paginationClass,
}
this.swiperOption.navigation = {
prevEl: '.' + this.prevClass,
nextEl: '.' + this.nextClass,
}
this.isShow = true
}
},
watch: {
imgs: {
handler(newValue) {
this.imgs = newValue
},
deep:true//深度监听
},
sIdx: {
handler(newValue) {
this.sIdx = newValue
},
deep:true//深度监听
},
}
}
</script>
二、父组件里面调用swiper组件
<BasisSwiper :imgs="item.imgs" :sIdx="index" v-if="isShowSwiper"></BasisSwiper>
这个很简单,把图片和产品循环的index传过去就行了
注意:切换品牌的时候,我是用了v-if来注销swiper组件,然后在nextTick里面(这个也很重要)数据处理完后再显示swiper相当于做了一个重置操作,这是必须要重置才能更新swiper的class
PS:我这个方法应该是比较一般的做法可能会有小bug没注意到,网上应该有更简单的,但之前找了一下不太满意所以自己写的,我觉得有时间的话可以自己多想想自己写,然后再去看别人的做法这样可以锻炼一下自己的逻辑思维能力吧,希望能帮助到大家
如果哪里有不对的地方,或者有更好的方法可以评论区说一下,希望能和大家交流
谢谢观看~