FilterTabs.vue
2.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<template>
<view :class="['flex overflow-x-auto no-scrollbar space-x-[24rpx]', wrapperClass]">
<view v-for="(item, index) in tabs" :key="getItemKey(item, index)"
:class="[
'px-[32rpx] py-[16rpx] rounded-full text-[28rpx] whitespace-nowrap transition-colors',
tabClass,
isActive(item, index) ? activeClassComputed : inactiveClassComputed
]"
@tap="handleSelect(item, index)"
>
<slot name="label" :item="item" :index="index">
{{ getItemLabel(item) }}
</slot>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
tabs: {
type: Array,
default: () => []
},
modelValue: {
type: [String, Number],
default: 0
},
labelKey: {
type: String,
default: 'title'
},
valueKey: {
type: String,
default: ''
},
wrapperClass: {
type: String,
default: ''
},
tabClass: {
type: String,
default: ''
},
activeClass: {
type: String,
default: ''
},
inactiveClass: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue', 'change'])
const activeClassComputed = computed(() => {
return props.activeClass || 'bg-[#2563EB] text-white'
})
const inactiveClassComputed = computed(() => {
return props.inactiveClass || 'bg-[#F3F4F6] text-[#6B7280]'
})
const getItemLabel = (item) => {
if (typeof item === 'string') return item
return item?.[props.labelKey] ?? ''
}
const getItemValue = (item, index) => {
if (typeof item !== 'object' || item === null) return index
if (props.valueKey && item[props.valueKey] !== undefined) return item[props.valueKey]
return index
}
const getItemKey = (item, index) => {
const value = getItemValue(item, index)
return value ?? index
}
const isActive = (item, index) => {
return getItemValue(item, index) === props.modelValue
}
const handleSelect = (item, index) => {
const value = getItemValue(item, index)
if (value === props.modelValue) return
emit('update:modelValue', value)
emit('change', value)
}
</script>
<style lang="less" scoped>
:deep(.no-scrollbar::-webkit-scrollbar) {
display: none;
width: 0;
height: 0;
}
:deep(.no-scrollbar) {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>