风格
通过type设置风格,支持三种风格card、borderCard、line
核心代码
组件双向绑定
modelVal: {
type: Number | String,
required: true
},
model: {
prop: 'modelVal',
event: 'change'
}
this.$emit('change', this.active)
代码
<template>
<div
:class="['tabs', { 'tabs-card': type === 'card' }, { 'tabs-boder-card': type === 'borderCard' }, { 'tabs-line': type === 'line' }]"
:style="{ 'height': height }">
<div class="tabs-nav">
<div v-if="type === 'line'" class="active-bar"
:style="{ 'width': activeBarWidth + 'px', 'transform': `translateX(${moveNum}px)` }"></div>
<div v-for="(item, index) in list" :key="index" :class="['tabs-item', { 'active': active === index }]"
@click="switchTab(index, item)">
{{ item[showLabel] }}
</div>
</div>
</div>
</template>
<script>
export default {
props: {
type: {
type: String,
default: 'card' // card borderCard line
},
list: {
type: Array,
default: () => []
},
showLabel: {
type: String,
default: 'label'
},
modelVal: {
type: Number | String,
required: true
},
height: {
type: String,
default: '42px'
}
},
model: {
prop: 'modelVal',
event: 'change'
},
data() {
return {
active: Number(this.modelVal),
moveNum: 0, // 移动距离
activeBarWidth: 0 // line风格下状态条宽
}
},
watch: {
'list': {
handler() {
this.$nextTick(() => {
let li = document.querySelectorAll('.tabs>.tabs-nav>.tabs-item')[0]
this.activeBarWidth = li ? li.offsetWidth : 0
})
},
immediate: true
}
},
methods: {
switchTab(index, item) {
this.active = index
if (this.type === 'line') {
const lis = document.querySelectorAll('.tabs>.tabs-nav>.tabs-item')
let num = 0
for (let i = 0; i < this.active; i++) {
num += lis[i].offsetWidth
}
this.moveNum = num
this.activeBarWidth = lis[this.active].offsetWidth
}
this.$emit('change', this.active)
this.$emit('switchTab', { active: this.active, row: item })
}
}
}
</script>
<style lang="scss" scoped>
.tabs {
width: 100%;
font-size: 16px;
font-weight: 400;
font-family: PingFangSC-Regular, PingFang SC;
color: #333333;
}
@import url('./tabsCard.scss');
@import url('./tabsBorderCard.scss');
@import url('./tabsLine.scss');
</style>
scss
tabsBorderCard.scss
.tabs-boder-card {
border-bottom: 1px solid #E5E7ED;
.tabs-nav {
display: flex;
.tabs-item {
padding: 10px 25px;
border: 1px solid #E5E7ED;
background-color: #F6F6F6;
cursor: pointer;
box-sizing: border-box;
}
.active {
color: #36CFC9;
border-top: 2px solid #36CFC9;
border-bottom: none;
background-color: #fff;
}
}
}
tabsCard.scss
.tabs-card {
border-bottom: 1px solid #36CFC9;
.tabs-nav {
height: 100%;
display: flex;
.tabs-item {
height: 100%;
padding: 0 10px;
line-height: 42px;
cursor: pointer;
box-sizing: border-box;
}
.active {
color: #FFFFFF;
background: #36CFC9;
border-radius: 8px 8px 0px 0px;
}
}
}
tabsLine.scss
.tabs-line {
border-bottom: 2px solid #ECECEC;
.tabs-nav {
display: flex;
position: relative;
.tabs-item {
padding: 10px 16px;
cursor: pointer;
box-sizing: border-box;
}
.active {
color: #36CFC9;
}
.active-bar {
height: 2px;
position: absolute;
bottom: -2px;
left: 0;
background-color: #36CFC9;
transition: all 0.5s ease;
}
}
}