一、可横向滑动的 tab
效果图:
实现:
封装组件:
<template>
<view class="content">
<view class="hand">
<scroll-view scroll-x="true" class="scroll-class">
<view class="dataInfo">
<view
class="dataList"
v-for="(item, index) in tabList"
:key="index"
@click="changeTab(index)"
>
<view :class="tabIndex == index ? 'activite' : ''" class="name">{{
item.label
}}</view>
<view :class="tabIndex == index ? 'active-line' : ''"></view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name: "baseTab",
props: {
tabList: {
type: Array,
default: () => [],
},
tabIndex: {
type: Number,
default: 0,
},
},
data() {
return {};
},
methods: {
changeTab(index) {
this.$emit("changeTab", index);
},
},
};
</script>
<style lang="less" scoped>
.content {
.hand {
.dataInfo {
display: flex;
text-align: center;
width: 100%;
.dataList {
.name {
font-size: 28rpx;
color: #bdbdbd;
display: block;
line-height: 52rpx;
width: 152rpx;
}
.name.activite {
color: #333333;
}
.active-line {
height: 6rpx;
width: 100rpx;
background: #3ec3ae;
border-radius: 2rpx;
margin: 0 auto;
}
}
}
}
.scroll-class {
white-space: nowrap;
border-bottom: 2rpx solid #e1e4e6;
}
}
</style>
页面调用:
<base-tab :tabIndex="tabIndex" :tabList="tabList" @changeTab="changeTab" ></base-tab>
export default{
data(){
return{
tabIndex: 0,
tabList: [
{ label: "第一" },
{ label: "第二" },
{ label: "第三" },
{ label: "第四" },
{ label: "第五" },
{ label: "第六" },
{ label: "第七" },
],
}
}
}
二、不可滑动的 tab
效果图二:
实现:
方法一:
组件代码:
<template>
<view>
<view class="tab-box">
<view
class="tab-item"
@click="chooseTab(index)"
:class="{ active: index === currentTab }"
v-for="(item, index) in tabList"
:key="index"
>
{{ item[labelKey] }}
</view>
</view>
</view>
</template>
<script>
export default {
name: "baseTab",
props: {
tabList: {
type: Array,
default: () => [],
},
labelKey: {
type: String,
default: "label",
},
tabIndex: {
type: [Number, String],
default: 0,
},
},
data() {
return {
currentTab: this.tabIndex,
};
},
methods: {
chooseTab(index) {
this.currentTab = index;
this.$emit("chooseTab", index);
},
},
};
</script>
<style lang="less" scoped>
.tab-box {
display: flex;
align-items: center;
margin-bottom: 30rpx;
border-bottom: 1rpx solid #eee;
.tab-item {
flex: 1;
position: relative;
top: 4rpx;
line-height: 37rpx;
padding: 0 0 15rpx;
text-align: center;
}
.active {
color: #0f5eee;
font-weight: bold;
border-bottom: 6rpx solid #0f5eee;
}
}
</style>
方法二:
每个tab是否平分自动计算宽度
组件代码:
<template>
<view class="tab-con">
<view class="tab-wrapper">
<view
v-for="(item, index) in tabList"
:key="index"
class="tab-item"
style="width: 800rpx"
@click="changeTab(index)"
:class="{ 'tab-item-active': index === tabIndex }"
>
<text>{{ item[labelKey] }} </text>
<view class="active-line"></view>
</view>
</view>
<view class="tab-wrapper-bottom"></view>
</view>
</template>
<script>
export default {
name: "baseTab",
props: {
tabIndex: {
type: [String, Number],
default: 0,
},
tabList: {
type: Array,
default: () => [],
},
labelKey: {
type: String,
default: "label",
},
},
data() {
return {};
},
computed: {
widthPercent() {
const point = 1 / this.tabList.length;
const formated = Number(point * 100).toFixed(2);
return `${formated}%`;
},
},
methods: {
changeTab(index) {
this.$emit("changeTab", index);
},
},
};
</script>
<style lang="less" scoped>
.tab-wrapper {
height: 52rpx;
display: flex;
align-items: center;
justify-content: center;
}
.tab-item {
font-size: 28rpx;
line-height: 38rpx;
color: #bdbdbd;
display: flex;
align-items: center;
position: relative;
justify-content: center;
font-family: Microsoft YaHei;
}
.tab-item-active {
color: #333333;
height: 52rpx;
box-sizing: border-box;
}
.tab-item-active .active-line {
height: 6rpx;
width: 100rpx;
background: #3ec3ae;
border-radius: 2rpx;
position: absolute;
bottom: -12rpx;
}
.tab-wrapper-bottom {
height: 2rpx;
background: #e1e4e6;
margin-top: 8rpx;
}
</style>
页面引用:
<base-tab :tabIndex="tabIndex" :tabList="tabList" @changeTab="changeTab"></base-tab>
data(){
tabIndex: 0,
tabList: [
{ label: "第一" },
{ label: "第二" },
{ label: "第三" },
],
}