最近刚开始用swiper的swiper-slide做滑动的功能,就掉进一个大坑,久久无法脱身……
终于在多番与大神交流之后,有了较大的进展,解决了这个问题,记录一下以示庆祝。
一、还原问题场景:
1、需求:
(1)做一个左右手动滑动图片的显示卡片(左右各有一个按钮);
(2)分大屏显示和小屏显示:大屏显示3张图片,小屏显示2张图片;
(3)若从小屏的b、c图片切换到大屏,不手动进行滑动按钮进行切换的情况下,再次回到小屏还是显示b、c图片。
2、问题:
对于今天讨论的问题,为了方便清晰的描述,假设数据的返回顺序为a、b、c、d……
(1)正常情况下:
若当前小屏显示的为图片b,c,在切换为大屏时存在两种情况:
(一)若b,c图片不是待显示数据的最后两张图片时,则切换到大屏的时候显示b、c图片后边紧接着的d图片,即大屏显示的图片从左到右的顺序是b、c、d;
(二)若b、c为当前待显示数据的最后两张时,则切换到大屏需要显示三张图片时,swiper会自动从紧挨b数据的上一条数据取图片a进行展示,即大屏显示的图片从左到右的顺序是a、b、c;
在两种情况下不进行滑动切换,当再次切回小屏时,小屏显示的图片从左向右依次为b、c(当前活动块索引activeIndex的值为b);
(2)异常情况:
当b、c为当前待显示数据的最后两张时,则切换到大屏需要显示三张图片时,swiper会自动从紧挨b数据的上一条数据取图片a进行展示,即大屏显示的图片从左到右的顺序是a、b、c;此时在大屏时当前活动块的索引为a,在切回小屏的时候swiper会自动将当前索引activeIndex的值自动加1,即在小屏时依然显示b、c图片(最后两张),这是正常(我们所需要)的逻辑;
然而~
当b图片不是待显示数据的最后两张图片之一,但c图片是待显示数据的倒数第两张图片时,从小屏的b、c图片切换到大屏时,还是会自动取b、c紧接着的下一条数据的图片d进行展示,即大屏的时候从左到右依次显示的顺序是b、c、d,这时swiper组件检测到c、d已经是最后两张图片了,所以在切回小屏的时候会将当前的情况视为c、d为当前待显示数据的最后两张,即小屏从左到右的显示顺序会变为c、d,这与我们的期望不符(我们需要切回小屏时依然显示b、c图片)。
二、问题分析:
设置一个可以记录在小屏时候活动块当前索引activeIndex值的变量smallActiveIndex,每次在大屏切换回小屏的时候直接当活动块滑动到smallActiveIndex记录的位置即可。
目前说起来是比较简单的,但是当时写代码的时候平了好久的坑……
因为牵扯到手动点击按钮改变activeIndex的值,因此需要slideChange方法在activeIndex改变时被触发,以记录手动点击之后活动块的索引;但是当活动块索引为倒数第三条数据时,切换大---》小屏之后,活动块索引会自动加1,引起slideChange被触发,导致记录的smallActiveIndex不准确……
那么,问题转换为如何咋大小瓶切换时不要触发slideChange方法?
哈哈,加个条件判断就解决了呀~~~
即若当前屏幕被改变的时候,导致触发slideChange方法,直接return掉即可,就可以实现我们用slideChange只记录点击按钮事件时活动块的值。
三、解决问题:
const that = this;
this.swiperOption.on.resize = () => {
this.width = document.body.clientWidth;
this.setActiveIndex();
}
// 在当前活动块切换到另一个时执行(activeIndex发生改变),一般是在点击控制组件、释放滑动的时间点。
this.swiperOption.on.slideChange = () => {
// 屏幕大小发生变化时,不触发slideChange方法,以确保smallActiveIndex记录的值为实时手动切换的活动块的索引(即当屏幕大小发生变化引起swiper的activeIndex自动变化时不会记录为smallActiveIndex)
if (this.width !== document.body.clientWidth) return;
if (document.body.clientWidth < Constans.ScreenDisplay.lg) {
// 记录小屏时的活动块索引
that.smallActiveIndex = that.$refs.swiper.$swiper.activeIndex;
}
}
setActiveIndex() {
if (document.body.clientWidth < Constans.ScreenDisplay.lg) {
// 当屏幕缩小之后,直接将活动块移动到记录手动滑动的索引位置
let index = this.smallActiveIndex;
this.$refs.swiper.$swiper.slideTo(index, 0);
}
}
只需要把对应的方法放进对应的模块中即可,全部直接复制粘贴不一定能正确运行哈!