323 lines
7.2 KiB
Vue
323 lines
7.2 KiB
Vue
<!-- tabbar组件 -->
|
||
<template>
|
||
<view class="TabControl" :style="[tabControlStyle]">
|
||
<scroll-view scroll-x="true" :style="'background-color:'+bgc+';top:'+top+'px;'" :class="fixed?'fxied':''" :scroll-left='scrollLeft' scroll-with-animation id="tabcard">
|
||
<image src="@/static/signUp/ico_return@3x.png" class="goBackImg" mode="" @click="goBack" v-if="goBackImg"></image>
|
||
<view class="tabList" :style="[tabListStyle]">
|
||
<view
|
||
:class="'tabItem'+(currentIndex==index?' thisOpenSelect':'')"
|
||
:style="[tabItemStyle]"
|
||
v-for="(item,index) in values"
|
||
:id="'item'+index"
|
||
:key='index'
|
||
@click="_onClick(item, index)">
|
||
<view class="tabItemName">
|
||
<text :style="(currentIndex==index?'font-size:'+activeSize+'rpx;color:'+activeColor:'font-size:'+itemSize+'rpx')">{{ item.name }}</text>
|
||
<!-- 排序箭头显示 -->
|
||
<view
|
||
v-show='item.sort && item.sortType !== 1'
|
||
class="arrow"
|
||
:style="'transform: rotate(' + (([4, 2].indexOf(item.sortType) !== -1) ? '180' : '0') + 'deg);'" />
|
||
</view>
|
||
<!-- 激活下划线(如果需要显示,则sort不要设置) -->
|
||
<view v-if='activeLineShow' class="activeLine" :style="{'background-color': activeLineColor}"></view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name:'TabControl',
|
||
props:{
|
||
//是否显示返回箭头
|
||
goBackImg: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 当前激活项
|
||
current: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
// tab 集合
|
||
values: {
|
||
type: Array,
|
||
default () {
|
||
return []
|
||
}
|
||
},
|
||
// 整体背景色
|
||
bgc:{
|
||
type: String,
|
||
default: '#fff'
|
||
},
|
||
// 是否开启固定位置
|
||
fixed: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 是否开启tabBar滚动
|
||
scrollFlag: {
|
||
type:Boolean,
|
||
default:false
|
||
},
|
||
// 激活下划线的宽度
|
||
lineWidth: {
|
||
type: Number,
|
||
default: 48
|
||
},
|
||
// tab 文本正常时的字体大小
|
||
itemSize: {
|
||
type: Number,
|
||
default: 28
|
||
},
|
||
// tab 文本激活时的字体大小
|
||
activeSize: {
|
||
type: Number,
|
||
default: 28
|
||
},
|
||
// tab 文本正常时的字体颜色
|
||
activeColor: {
|
||
type: String,
|
||
default: '#FE4066'
|
||
},
|
||
// 开启固定位置之后的,top设置
|
||
top: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
// 每个tab项是否等宽显示
|
||
isEqually: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 父级与tab项的高度
|
||
tabListHeight: {
|
||
type: [Number, String],
|
||
default: 40
|
||
},
|
||
// 是否显示激活下划线
|
||
activeLineShow: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
//下划线颜色
|
||
activeLineColor: {
|
||
type: String,
|
||
default: '#FE4066'
|
||
},
|
||
tabWrapNeedHeight: {
|
||
type: Boolean,
|
||
default: true
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
currentIndex: 0,
|
||
windowWidth:0, //设备宽度
|
||
leftList:[], //选项距离左边的距离
|
||
widthList:[], //选项宽度
|
||
scrollLeft:0, //移动距离
|
||
newScroll:0, //上一次移动距离(用来判断是左滑还是右滑)
|
||
wornScroll:0, //上一次移动距离(用来判断是左滑还是右滑)
|
||
};
|
||
},
|
||
watch: {
|
||
current(val) {
|
||
if (val !== this.currentIndex) {
|
||
this.currentIndex = val
|
||
if(this.scrollFlag){
|
||
this.tabListScroll(val)
|
||
}
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
tabItemStyle: function () {
|
||
const _style = {}
|
||
if (this.isEqually) {
|
||
_style['width'] = this.windowWidth/this.values.length + 'px'
|
||
_style['margin-right'] = 0
|
||
}
|
||
if (!this.activeLineShow) {
|
||
_style['height'] = '100%'
|
||
}
|
||
return _style
|
||
},
|
||
tabListStyle: function () {
|
||
const _style = {
|
||
height: this.tabListHeight + 'px'
|
||
}
|
||
if (this.isEqually) {
|
||
_style['display'] = 'flex'
|
||
_style['justify-content'] = 'space-between'
|
||
_style['padding-left'] = 0
|
||
}
|
||
return _style
|
||
},
|
||
tabControlStyle: function () {
|
||
const _style = {}
|
||
if (this.tabWrapNeedHeight) {
|
||
_style['height'] = this.tabListHeight + 'px'
|
||
}
|
||
return _style
|
||
}
|
||
},
|
||
created() {
|
||
this.currentIndex = this.current
|
||
if(this.scrollFlag){
|
||
setTimeout(()=>{
|
||
this.tabListScroll(this.current)
|
||
},300)
|
||
}
|
||
},
|
||
mounted(){
|
||
setTimeout(()=>{
|
||
uni.createSelectorQuery().in(this).select("#tabcard").boundingClientRect((res)=>{
|
||
this.$emit('getTabCardHeight', {height:res.height})
|
||
}).exec()
|
||
uni.getSystemInfo({
|
||
success: (res)=> {
|
||
this.windowWidth = res.windowWidth;
|
||
// console.log(this.windowWidth);
|
||
this.values.forEach((i,v)=>{
|
||
let info = uni.createSelectorQuery().in(this);
|
||
info.select("#item"+v).boundingClientRect((res)=>{
|
||
// 获取第一个元素到左边的距离
|
||
// if(v==0){
|
||
// this.startLenght = res.left
|
||
// }
|
||
this.widthList.push(res.width)
|
||
this.leftList.push(res.left)
|
||
|
||
}).exec()
|
||
|
||
})
|
||
// console.log(this.leftList)
|
||
// console.log(this.widthList)
|
||
}
|
||
});
|
||
})
|
||
},
|
||
methods: {
|
||
goBack(){
|
||
uni.navigateBack({
|
||
|
||
})
|
||
},
|
||
_onClick(item, index) {
|
||
this.$emit('clickItem', { currentIndex: index, ...item })
|
||
if (this.currentIndex !== index) {
|
||
this.currentIndex = index
|
||
// 开启滚动
|
||
if(this.scrollFlag){
|
||
this.tabListScroll(index)
|
||
}
|
||
}
|
||
},
|
||
// 选项移动
|
||
tabListScroll(index){
|
||
let scoll = 0;
|
||
this.wornScroll = index;
|
||
// this.wornScroll-this.newScroll>0 在向左滑 ←←←←←
|
||
if(this.wornScroll-this.newScroll>0){
|
||
for(let i = 0;i<this.leftList.length;i++){
|
||
if(i>1&&i==this.currentIndex){
|
||
scoll = this.leftList[i-1]
|
||
}
|
||
}
|
||
// console.log('在向左滑',scoll)
|
||
}else{
|
||
if(index>1){
|
||
for(let i = 0;i<this.leftList.length;i++){
|
||
if(i<index-1){
|
||
scoll = this.leftList[i]
|
||
}
|
||
}
|
||
}else{
|
||
scoll = 0
|
||
}
|
||
// console.log('在向右滑')
|
||
}
|
||
this.newScroll = this.wornScroll;
|
||
this.scrollLeft = scoll;
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.goBackImg{
|
||
width: 18upx;
|
||
height: 32upx;
|
||
position: absolute;
|
||
left: 30upx;
|
||
top: 30upx;
|
||
z-index: 999;
|
||
}
|
||
.TabControl {
|
||
.fxied {
|
||
position: fixed;
|
||
z-index: 2;
|
||
}
|
||
.tabList {
|
||
height: 80rpx;
|
||
padding-left: 24rpx;
|
||
white-space: nowrap;
|
||
text-align: center;
|
||
.tabItem {
|
||
position: relative;
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 60rpx;
|
||
.tabItemName {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text {
|
||
line-height: 44rpx;
|
||
color: #564F5F;
|
||
transition: all 0.3s ease 0s;
|
||
}
|
||
.arrow {
|
||
width: 10rpx;
|
||
height: 6rpx;
|
||
margin-left: 6rpx;
|
||
background: url('@/static/components/triangular_arrow.png');
|
||
background-size: 100% 100%;
|
||
// transform: rotate(180deg);
|
||
}
|
||
}
|
||
.activeLine {
|
||
width: 48rpx;
|
||
height: 8rpx;
|
||
border-radius: 4rpx;
|
||
// background-color: #FE4066;
|
||
margin: 8rpx auto 0;
|
||
opacity: 0;
|
||
transition: all 0.5s ease 0s;
|
||
}
|
||
}
|
||
.tabItem:first-child {
|
||
// margin-left: 22rpx;
|
||
}
|
||
.tabItem:last-child {
|
||
margin-right: 24rpx;
|
||
}
|
||
.thisOpenSelect {
|
||
text {
|
||
color: #333;
|
||
font-weight: 600;
|
||
}
|
||
.activeLine {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|