You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

87 lines
1.8 KiB

<template>
<view class="tabs" ref="tab">
<view v-for="item in options" :class="modelValue === item.value ? 'tabs-item active' : 'tabs-item'" @tap="changeTab(item.value)">
<view class="tabs-item-label" :style="{width: labelFull ? '100%' : 'auto'}">{{ item.text }}</view>
</view>
<view class="tab-active-bar" :style="{width: `${width}px`, transform: `translateX(${left}px)`}"></view>
</view>
</template>
<script setup>
import { defineProps, defineEmits, nextTick, ref, onMounted } from 'vue'
defineProps({
options: {
type: Array,
default: []
},
modelValue: {
type: String,
default: ''
},
labelFull: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['update:modelValue']);
const tab = ref()
const width = ref(0)
const left = ref(0)
function changeTab(value) {
emit('update:modelValue', value);
nextTick(() => {
getActiveBarStyle()
})
}
onMounted(() => {
nextTick(() => {
getActiveBarStyle()
})
})
function getActiveBarStyle() {
const query = uni.createSelectorQuery().in(this);
query
.select(".tabs-item.active>.tabs-item-label")
.boundingClientRect((data) => {
width.value = data.width;
left.value = data.left;
})
.exec();
}
</script>
<style lang="scss" scoped>
.tabs {
display: flex;
box-shadow: inset 0 -1px 0 0 #eee;
position: relative;
.tabs-item {
width: 50%;
display: flex;
justify-content: center;
.tabs-item-label {
text-align: center;
height: 84rpx;
line-height: 84rpx;
color: #333;
}
&.active {
.tabs-item-label {
color: var(--primary-color);
}
}
}
.tab-active-bar {
height: 2px;
position: absolute;
bottom: 0;
transition: all .3s;
background-color: var(--primary-color);
}
}
</style>