效果图在上面,直接上代码吧-_-
<!-- 会员和至尊会员tab -->
<div
class="member-card-tab-section"
ref="memberCardTab"
>
<div
v-for="(item, index) in memberTabList"
:key="index"
:class="['normal-superme-member', `${index === 0 ? 'normal' : 'superme'}-member`,
currentIndex === index ? 'bright-color' : 'grey-color']"
>
<div
class="normal-superme-member-text"
@click="changeTab(index)"
>
{{ item }}
<div
class="check-line"
ref="checkLine"
v-show="currentIndex === index"
/>
</div>
</div>
</div>
<!-- 滑动切换tab -->
<div
class="superme-normal-member"
@touchstart="touchStart"
@touchend="touchEnd"
>
<div class="member-swiper">
<ul :style="{'transform': `translateX(${offsetVal}px)`}">
<li
v-for="(item, index) in 2"
:key="index"
ref="memberItem"
>
XXXXXXXXXXXXXXXXXXXXX业务样式代码~
</li>
</ul>
</div>
</div>
.superme-normal-member {
@include position(inherit);
overflow: hidden;
margin-bottom: 164px;
.member-swiper {
ul {
white-space: nowrap;
height: 100%;
padding: 0;
transition: all .5s;
li {
display: inline-block;
}
}
}
}
.member-card-tab-section {
position: absolute;
left: 0px;
top: 44px;
display: flex;
font-size: 32px;
font-weight: 500;
justify-content: center;
z-index: 2;
width: 100%;
.normal-member {
padding-left: 87px;
}
.superme-member {
padding-right: 87px;
}
.normal-superme-member {
height: 44px;
line-height: 44px;
width: 100%;
}
.normal-superme-member-text {
width: 100%;
position: relative;
text-align: center;
.check-line{
position: absolute;
left: 124px;
top: 55px;
@include backgroundImage(40px, 4px, $imgBaseUrl + '/line.jpg');
}
}
.bright-color {
color: #BE9F8F;
}
.grey-color {
color: rgba(190, 159, 143, 0.5);
}
}
js代码
data(){
return {
memberTabList: ['会员', '至尊会员'],
offsetVal: 0, // 位移
currentIndex: 0, // swiper目前的索引
firstTouchX: 0, // 首次位移
pageLength: 2,
firstSvipPacket: {}, // 至尊会员第一个套餐
firstVipPacket: {}, // 普通会员第一个套餐
packetList: [], // 套餐
memberTabList: ['会员', '至尊会员'],
triggerDistance: 50, // 阈值
}
},
watch: {
currentIndex (val) {
this.offsetVal = -(this.$refs.memberItem[0].offsetWidth * val)
},
},
methods: {
// 触摸
touchStart (event) {
event.stopPropagation()
this.firstTouchX = parseInt(event.changedTouches[0].clientX)
},
touchEnd (event) {
event.stopPropagation()
const diff = event.changedTouches[0].clientX - this.firstTouchX
if (Math.abs(diff) > this.triggerDistance) {
diff > 0 ? this.prePage() : this.nextPage()
}
},
// 从左往右滑动
prePage () {
this.currentIndex === 0 ? this.currentIndex = 0 : this.currentIndex--
},
// 从右边往左边滑动
nextPage () {
this.currentIndex === (this.pageLength - 1) ? this.currentIndex =
(this.pageLength - 1) : this.currentIndex++
},
changeTab (index) {
this.currentIndex = index
},
}
思路与重点:
- ul 里面有两个li进行平铺(display:inline-block), 假设我们默认的是第一张,currentIndex为0, index为0,那么offsetVal就是为0
- currentIndex也就是tab目前的index,首次获取肯定是从后台返回,或者产品要求的默认哪个,或者默认第一个,具体看要求
- 那么改变currentIndex有两种途径,第一种就是通过点击tab改变,相对应的changeTab方法,第二种是用手滑动,对应触发touchStart,touchEnd
- 确定翻页,currentIndex有变化,然后根据currentIndex变化往左或者往右去平移屏幕宽度的一个大小(主要是利用transform:translateX)的特性去做平移动,同时设置transition: all .5s;的过度效果
const diff = event.changedTouches[0].clientX - this.firstTouchX
if (Math.abs(diff) > this.triggerDistance) {
diff > 0 ? this.prePage() : this.nextPage()
// diff如果大于0表示,表示从左往右滑动,如果是小于0 表示从右边往左滑动
}
clientX/Y获取到的是触发点相对浏览器可视区域左上角距离,不随页面滚动而改变。(兼容性:所有浏览器均支持)
这里为什么要对比一个triggerDistance,这是一个阈值,如果不做判断,不管滑动多少距离,都会进行翻页,或者别人只是手机稍作移动,并不想 翻页.所以要他移动一定距离,才进行翻页处理
好好生活-_-