346 lines
7.0 KiB
Vue
346 lines
7.0 KiB
Vue
![]() |
<template>
|
|||
|
<view class="tui-tabs-view"
|
|||
|
:class="[isFixed ? 'tui-tabs-fixed' : 'tui-tabs-relative', unlined ? 'tui-unlined' : '']" :style="{
|
|||
|
width: tabsWidth + 'px',
|
|||
|
height: height + 'rpx',
|
|||
|
padding: `0 ${padding}rpx`,
|
|||
|
background: backgroundColor,
|
|||
|
top: isFixed ? top + 'px' : 'auto',
|
|||
|
zIndex: isFixed ? zIndex : 'auto'
|
|||
|
}" v-if="tabsWidth>0">
|
|||
|
<view v-for="(item, index) in tabs" :key="index" class="tui-tabs-item"
|
|||
|
:style="{ width: getItemWidth,height: height + 'rpx' }" @tap.stop="swichTabs(index)">
|
|||
|
<view class="tui-tabs-title" :class="{'tui-tabs-disabled': item.disabled }" :style="{
|
|||
|
color: currentTab == index ? getSelectedColor : color,
|
|||
|
fontSize: size + 'rpx',
|
|||
|
fontWeight: bold && currentTab == index ? 'bold' : 'normal',transform:`scale(${currentTab == index?scale:1})`
|
|||
|
}">
|
|||
|
{{ item[field] }} <text v-if="item[badgeField]">({{item[badgeField]}})</text>
|
|||
|
<view :class="[item.isDot ? 'tui-badge__dot' : 'tui-tabs__badge']"
|
|||
|
:style="{ color: badgeColor, backgroundColor: getBadgeBgColor }"
|
|||
|
v-if="item.isDot">
|
|||
|
{{ item.isDot ? '' : item[badgeField] }}
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
<view v-if="isSlider" class="tui-tabs-slider" :style="{
|
|||
|
transform: 'translateX(' + scrollLeft + 'px)',
|
|||
|
width: sliderWidth + 'rpx',
|
|||
|
height: sliderHeight + 'rpx',
|
|||
|
borderRadius: sliderRadius,
|
|||
|
bottom: bottom,
|
|||
|
background: getSliderBgColor,
|
|||
|
marginBottom: bottom == '50%' ? '-' + sliderHeight / 2 + 'rpx' : 0
|
|||
|
}"></view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
export default {
|
|||
|
name: 'tuiTabs',
|
|||
|
emits: ['change'],
|
|||
|
props: {
|
|||
|
//标签页
|
|||
|
tabs: {
|
|||
|
type: Array,
|
|||
|
default () {
|
|||
|
return [];
|
|||
|
}
|
|||
|
},
|
|||
|
//显示文本字段名称
|
|||
|
field: {
|
|||
|
type: String,
|
|||
|
default: 'name'
|
|||
|
},
|
|||
|
badgeField: {
|
|||
|
type: String,
|
|||
|
default: 'num'
|
|||
|
},
|
|||
|
//tabs宽度,不传值则默认使用windowWidth,单位px
|
|||
|
width: {
|
|||
|
type: [Number, String],
|
|||
|
default: 0
|
|||
|
},
|
|||
|
//rpx
|
|||
|
height: {
|
|||
|
type: Number,
|
|||
|
default: 80
|
|||
|
},
|
|||
|
//rpx 只对左右padding起作用,上下为0
|
|||
|
padding: {
|
|||
|
type: Number,
|
|||
|
default: 30
|
|||
|
},
|
|||
|
//背景色
|
|||
|
backgroundColor: {
|
|||
|
type: String,
|
|||
|
default: '#FFFFFF'
|
|||
|
},
|
|||
|
//是否固定
|
|||
|
isFixed: {
|
|||
|
type: Boolean,
|
|||
|
default: false
|
|||
|
},
|
|||
|
//px
|
|||
|
top: {
|
|||
|
type: Number,
|
|||
|
// #ifndef H5
|
|||
|
default: 0,
|
|||
|
// #endif
|
|||
|
// #ifdef H5
|
|||
|
default: 44
|
|||
|
// #endif
|
|||
|
},
|
|||
|
//是否去掉底部线条
|
|||
|
unlined: {
|
|||
|
type: Boolean,
|
|||
|
default: false
|
|||
|
},
|
|||
|
//当前选项卡
|
|||
|
currentTab: {
|
|||
|
type: Number,
|
|||
|
default: 0
|
|||
|
},
|
|||
|
isSlider: {
|
|||
|
type: Boolean,
|
|||
|
default: true
|
|||
|
},
|
|||
|
//滑块宽度
|
|||
|
sliderWidth: {
|
|||
|
type: Number,
|
|||
|
default: 68
|
|||
|
},
|
|||
|
//滑块高度
|
|||
|
sliderHeight: {
|
|||
|
type: Number,
|
|||
|
default: 6
|
|||
|
},
|
|||
|
//滑块背景颜色
|
|||
|
sliderBgColor: {
|
|||
|
type: String,
|
|||
|
default: ''
|
|||
|
},
|
|||
|
sliderRadius: {
|
|||
|
type: String,
|
|||
|
default: '50rpx'
|
|||
|
},
|
|||
|
//滑块bottom
|
|||
|
bottom: {
|
|||
|
type: String,
|
|||
|
default: '0'
|
|||
|
},
|
|||
|
//标签页宽度
|
|||
|
itemWidth: {
|
|||
|
type: String,
|
|||
|
default: ''
|
|||
|
},
|
|||
|
//字体颜色
|
|||
|
color: {
|
|||
|
type: String,
|
|||
|
default: '#666'
|
|||
|
},
|
|||
|
//选中后字体颜色
|
|||
|
selectedColor: {
|
|||
|
type: String,
|
|||
|
default: ''
|
|||
|
},
|
|||
|
//字体大小
|
|||
|
size: {
|
|||
|
type: Number,
|
|||
|
default: 28
|
|||
|
},
|
|||
|
//选中后 是否加粗 ,未选中则无效
|
|||
|
bold: {
|
|||
|
type: Boolean,
|
|||
|
default: false
|
|||
|
},
|
|||
|
//2.3.0+
|
|||
|
scale: {
|
|||
|
type: [Number, String],
|
|||
|
default: 1
|
|||
|
},
|
|||
|
//角标字体颜色
|
|||
|
badgeColor: {
|
|||
|
type: String,
|
|||
|
default: '#fff'
|
|||
|
},
|
|||
|
//角标背景颜色
|
|||
|
badgeBgColor: {
|
|||
|
type: String,
|
|||
|
default: ''
|
|||
|
},
|
|||
|
zIndex: {
|
|||
|
type: [Number, String],
|
|||
|
default: 996
|
|||
|
}
|
|||
|
},
|
|||
|
watch: {
|
|||
|
currentTab() {
|
|||
|
this.checkCor();
|
|||
|
},
|
|||
|
tabs() {
|
|||
|
this.checkCor();
|
|||
|
},
|
|||
|
width(val) {
|
|||
|
this.tabsWidth = val;
|
|||
|
this.checkCor();
|
|||
|
}
|
|||
|
},
|
|||
|
computed: {
|
|||
|
getItemWidth() {
|
|||
|
let width = 100 / (this.tabs.length || 4) + '%'
|
|||
|
return this.itemWidth ? this.itemWidth : width
|
|||
|
},
|
|||
|
getSliderBgColor() {
|
|||
|
return this.sliderBgColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
|
|||
|
},
|
|||
|
getSelectedColor() {
|
|||
|
return this.selectedColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc';
|
|||
|
},
|
|||
|
getBadgeBgColor() {
|
|||
|
return this.badgeBgColor || (uni && uni.$tui && uni.$tui.color.pink) || '#f74d54';
|
|||
|
}
|
|||
|
},
|
|||
|
created() {
|
|||
|
// 高度自适应
|
|||
|
setTimeout(() => {
|
|||
|
uni.getSystemInfo({
|
|||
|
success: res => {
|
|||
|
this.winWidth = res.windowWidth;
|
|||
|
this.tabsWidth = this.width == 0 ? this.winWidth : Number(this.width);
|
|||
|
this.checkCor();
|
|||
|
}
|
|||
|
});
|
|||
|
}, 0);
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
winWidth: 0,
|
|||
|
tabsWidth: 0,
|
|||
|
scrollLeft: 0
|
|||
|
};
|
|||
|
},
|
|||
|
methods: {
|
|||
|
checkCor: function() {
|
|||
|
let tabsNum = this.tabs.length;
|
|||
|
let padding = uni.upx2px(Number(this.padding));
|
|||
|
let width = this.tabsWidth - padding * 2;
|
|||
|
let left = (width / tabsNum - uni.upx2px(Number(this.sliderWidth))) / 2 + padding;
|
|||
|
let scrollLeft = left;
|
|||
|
if (this.currentTab > 0) {
|
|||
|
scrollLeft = scrollLeft + (width / tabsNum) * this.currentTab;
|
|||
|
}
|
|||
|
this.scrollLeft = scrollLeft;
|
|||
|
},
|
|||
|
// 点击标题切换当前页时改变样式
|
|||
|
swichTabs: function(index) {
|
|||
|
let item = this.tabs[index];
|
|||
|
if (item && item.disabled) return;
|
|||
|
if (this.currentTab == index) {
|
|||
|
return false;
|
|||
|
} else {
|
|||
|
this.$emit('change', {
|
|||
|
index: Number(index),
|
|||
|
item: item
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
</script>
|
|||
|
|
|||
|
<style scoped>
|
|||
|
.tui-tabs-view {
|
|||
|
width: 100%;
|
|||
|
box-sizing: border-box;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: space-between;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-relative {
|
|||
|
position: relative;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-fixed {
|
|||
|
position: fixed;
|
|||
|
left: 0;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-fixed::before,
|
|||
|
.tui-tabs-relative::before {
|
|||
|
content: '';
|
|||
|
position: absolute;
|
|||
|
border-bottom: 1rpx solid #eaeef1;
|
|||
|
-webkit-transform: scaleY(0.5) translateZ(0);
|
|||
|
transform: scaleY(0.5) translateZ(0);
|
|||
|
transform-origin: 0 100%;
|
|||
|
bottom: 0;
|
|||
|
right: 0;
|
|||
|
left: 0;
|
|||
|
}
|
|||
|
|
|||
|
.tui-unlined::before {
|
|||
|
border-bottom: 0 !important;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-item {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
overflow: visible;
|
|||
|
/* #ifdef H5 */
|
|||
|
cursor: pointer;
|
|||
|
/* #endif */
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-disabled {
|
|||
|
opacity: 0.6;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-title {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
position: relative;
|
|||
|
z-index: 3;
|
|||
|
overflow: visible;
|
|||
|
transition: all 0.15s ease-in-out;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs-slider {
|
|||
|
position: absolute;
|
|||
|
left: 0;
|
|||
|
transition: all 0.3s ease-in-out;
|
|||
|
z-index: 1;
|
|||
|
transform-style: preserve-3d;
|
|||
|
}
|
|||
|
|
|||
|
.tui-tabs__badge {
|
|||
|
position: absolute;
|
|||
|
font-size: 24rpx;
|
|||
|
height: 32rpx;
|
|||
|
min-width: 20rpx;
|
|||
|
padding: 0 6rpx;
|
|||
|
border-radius: 40rpx;
|
|||
|
right: 0;
|
|||
|
top: 0;
|
|||
|
transform: translate(88%, -50%);
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
flex-shrink: 0;
|
|||
|
z-index: 4;
|
|||
|
font-weight: normal !important;
|
|||
|
}
|
|||
|
|
|||
|
.tui-badge__dot {
|
|||
|
position: absolute;
|
|||
|
height: 16rpx;
|
|||
|
width: 16rpx;
|
|||
|
border-radius: 50%;
|
|||
|
right: -10rpx;
|
|||
|
top: -10rpx;
|
|||
|
z-index: 4;
|
|||
|
}
|
|||
|
</style>
|