效果如图
子组件 followTabs.vue
<!-- followTabs -->
<template>
<div class="follow-tabs">
<div v-for="item in tabList" :key="item.value" :ref="`tabRef${item.value}`"
@click="tabClick(item.value)" class="follow-tab"
:class="{'active': item.value === tabActive}">
{{ item.label }}
</div>
<div class="follow-line" :style="{left}"></div>
</div>
</template>
<script>
export default {
name: 'followTabs',
props: {
// tabs栏目列表
tabList: {
type: Array,
default: () => [],
},
// 当前所在的tab
value: {
type: [String, Number],
default: '',
}
},
data() {
return {
left: 'auto', // 跟随线的定位
tabActive: this.value, // 当前tab
};
},
mounted() {
this.tabActive = this.value;
this.getElPositionInfo();
},
methods: {
tabClick(value) {
this.tabActive = value;
this.$emit('input', value); // 更新父元素绑定的tab
this.getElPositionInfo();
},
async getElPositionInfo() {
await this.$nextTick();
const refName = `tabRef${this.tabActive}`;
const elRef = this.$refs[refName] && this.$refs[refName][0];
const elPositionInfo = elRef ? elRef.getBoundingClientRect() : {};
// 此tab的left 加上tab宽度的一般,css样式中已经translateX(-50%) 所以此时跟随线会居中显示
this.left = `${parseInt(elPositionInfo.left, 10) + (parseInt(elPositionInfo.width / 2, 10))}px`;
}
},
};
</script>
<style lang="less" scoped>
.follow-tabs{
position: relative;
z-index: 3;
display: flex;
align-items: center;
justify-content: space-evenly;
width: 100%;
height: 80px;
line-height: 80px;
font-family: PingFangSC, PingFang SC;
.follow-tab{
position: relative;
font-size: 28px;
font-weight: 400;
padding: 0 10px;
color: #666666;
height: 100%;
line-height: inherit;
&.active{
font-weight: 500;
font-size: 30px;
color: #1989FA;
}
}
.follow-line{
position: absolute;
bottom: 0px;
width: 60px;
height: 4px;
transform: translateX(-30px);
border-radius: 2px;
background: #1989FA;
transition:left 0.2s linear;
}
}
</style>
父组件使用
<followTabs v-model="tabType" :tabList="tabList"></followTabs>
<script>
export default {
data() {
return {
tabType: 1,
tabList: [
{
label: '优秀',
value: 1,
},
{
label: '异常',
value: 2,
},
{
label: '亏损',
value: 3,
},
],
} ;
},
};
</script>