最近开发的一个微信小程序,首页顶部有一个 swiper 组件实现的轮播图效果,在安卓手机上显示是正常的,但是客户反馈在苹果手机上经常出现轮播图狂抖的问题。
其实这是 swiper 组件的一个常见问题,官方已经给出了 tips:
https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html
tip: 如果在bindchange的事件回调函数中使用setData改变current值,则有可能导致setData被不停地调用,因而通常情况下请在改变current值前检测source字段来判断是否是由于用户触摸引起。
解决方法1:
按照官方提示,在改变 current 值前检测 source:
<view class="swiperBox" style="{{defaultData.indicatorColors}}">
<swiper
class="slide-swiper"
style="height:{{defaultData.bannerheight}}rpx;"
indicator-dots="{{false}}"
autoplay="{{true}}"
interval="{{interval}}"
duration="{{duration}}"
indicator-color="{{defaultData.indicatorColor}}"
indicator-active-color="{{defaultData.indicatorActiveColor}}"
current="{{currentSwiper}}"
bindchange="swiperChange"
>
<block wx:for="{{defaultData.src}}" wx:key="s_id">
<swiper-item data-item="{{item}}">
<view class=" swiper-item">
<image class="swiper-item-img" src="{{item.imgUrl}}" mode="widthFix" />
</view>
</swiper-item>
</block>
</swiper>
<view class="dots {{defaultData.dotsType}}">
<block wx:for="{{defaultData.src}}" wx:key="src">
<view class="dot{{index == currentSwiper ? ' active' : ''}}" />
</block>
</view>
</view>
methods: {
swiperChange: function (e) {
let { current, source } = e.detail
if (source === 'autoplay' || source === 'touch') {
this.setData({
currentSwiper: current
})
}
},
}
解决方法2:
在动画播放结束后(@animationfinish)改变current的值,而不是一滑动(@change)就改变current的值。即用@animationfinish代替 @change。
@change与@animationfinish对比说明
1、相同点:都会改变current的值,current代表当前所在滑块的index
2、不同点:改变current的时机不同,@change滑动时立即改变,@animationfinish动画结束后改变!
说明:
如果想要自定义面板指示点,不建议与swiper共用一个索引值,最好将swiper与指示点的索引区分开,即用不同的变量,然后两者同步变化就可以了!
<template>
<view class="swipers-wrap">
<swiper @animationfinish="swiperChange" :current="currentSwiper" circular="true" class="swipers-view"
:autoplay="autoplay" @change="dotChange">
<block v-for="(item,index) in swiperList" :key="index">
<swiper-item>
<view class="swipers-best-hot-video">
美景展示~
</view>
<view class="swipers-image-view">
<image :src="item.imgUrl" mode="aspectFill" class="swipers-image"></image>
<view class="swipers-title">
{{item.title}}
</view>
</view>
</swiper-item>
</block>
</swiper>
<!--重置指示面板(小圆点)的样式 -->
<view class="swipers-dots">
<block v-for="(item,index) in swiperList" :key="index">
<view class="dot" :class="{active: currentDot == index}"></view>
</block>
</view>
</view>
</template>
<script>
export default {
data() {
return {
currentDot: 0, //指示面板对应的索引
currentSwiper: 0, //用来记录当前swiper对应的索引
autoplay: true,
swiperList:[
{
'imgUrl':'../../static/swiper.jpg',
'title':'白云朵朵!'
},
{
'imgUrl':'../../static/list.jpg',
'title':'蓝天绿树!'
},
{
'imgUrl':'../../static/user.jpg',
'title':'boy!'
}
]
}
},
methods: {
dotChange: function(e) {
this.currentDot = e.detail.current
},
swiperChange: function(e) {
this.currentSwiper = e.detail.current
},
}
}
</script>
<style>
.swipers-wrap {
height: auto;
position: relative;
background-color: blue;
padding: 0 15upx;
padding-bottom: 54upx;
}
.swipers-view {
height: 420upx;
}
.swipers-best-hot-video {
height: 90upx;
line-height: 90upx;
color: #f8f3bf;
font-size: 36upx;
text-align: center;
}
.swipers-image-view {
height: 100%;
position: relative;
z-index: 1;
}
.swipers-image {
width: 100%;
height: 100%;
}
.swipers-image-view .swipers-title {
position: absolute;
z-index: 99;
left: 25upx;
bottom: 105upx;
font-size: 24upx;
font-weight: bold;
color: #fff;
font-size: 36upx;
}
/*用来包裹所有的小圆点 */
.swipers-dots {
width: 100%;
height: 50upx;
display: flex;
flex-direction: row;
position: absolute;
left: 0;
bottom: 0upx;
/* border:1upx solid red; */
display: flex;
justify-content: center;
align-items: center;
/* border:1rpx solid green; */
}
/*未选中时的小圆点样式 */
.dot {
width: 6px;
height: 2upx;
width: 55upx;
background-color: #999;
margin: 0 10upx;
/* border:1upx solid red; */
}
/*选中以后的小圆点样式 */
.dot.active {
height: 2upx;
width: 80upx;
background-color: #fff;
margin: 0 10upx;
}
</style>


