效果图:
主要能力:选中的tab会自动移动到组件的中间位置,支持默认选中第几个tab,支持多级联动筛选,然后发送数据请求。
参考文章:uni_app组件实现tab选项卡滑动切换,支持默认选中,vue3+ts+setup_平谷一勺的博客-CSDN博客
废话不多说上菜了,
tags.vue组件
<template>
<view class="nav">
<scroll-view class="tabs" scroll-x="true" scroll-with-animation :scroll-left="scrollLeft">
<view class="tabs-scroll">
<view class="tabs-scroll_item" v-for=" (item,index) in itemList" :key="index"
:class="{'active':selectIndex==index}" @click="chenked(index)">
{{item.title}}
</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="ts">
import { getCurrentInstance, onMounted, ref, watch } from "vue";
const scrollLeft = ref<number>(0)
const selectIndex = ref<number>(0)
const itemList = ref<Array<ItabItem>>()
interface ItabItem {
title : string
width ?: number
left ?: number
id : number
type:number
}
interface Iprops {
tablist : Array<ItabItem>
defaultSelectIndex ?: number
}
const props = withDefaults(defineProps<Iprops>(), {
tablist: () => [],
defaultSelectIndex: 6
})
const emits=defineEmits<{
(e : 'select',value : ItabItem,index:number) : void
}>()
const chenked = (index:number) => {
selectIndex.value = index
scrollLeft.value = 0
for (let i = 0; i < index - 2; i++) {
scrollLeft.value = scrollLeft.value + itemList.value[i]?.width
}
emits('select',props.tablist[index],index)
}
onMounted(() => {
const query = uni.createSelectorQuery().in(getCurrentInstance());
query.selectAll('.tabs-scroll_item').boundingClientRect((data:Array<UniApp.NodeInfo>) => {
let dataLen = data.length;
for (let i = 0; i < dataLen; i++) {
// scroll-view 子元素组件距离左边栏的距离
itemList.value[i].left = data[i].left;
// scroll-view 子元素组件宽度
itemList.value[i].width = data[i].width
}
}).exec()
})
watch(() => [props.tablist, props.defaultSelectIndex], () => {
itemList.value = props.tablist
selectIndex.value = props.defaultSelectIndex
// if (props.defaultSelectIndex !== 0) {
setTimeout(() => {
chenked(props.defaultSelectIndex)
}, 50)
// }
}, {
immediate: true
})
</script>
<style lang="scss" scoped>
.nav {
margin-top: 10rpx;
z-index: 99;
width: 100%;
align-items: center;
.tabs {
flex: 1;
overflow: hidden;
box-sizing: border-box;
padding-left: 30rpx;
padding-right: 30rpx;
.tabs-scroll {
display: flex;
align-items: center;
flex-wrap: nowrap;
box-sizing: border-box;
.tabs-scroll_item {
// line-height: 60rpx;
margin-right: 35rpx;
flex-shrink: 0;
padding: 6rpx 12rpx;
display: flex;
justify-content: center;
font-size: 16px;
}
}
}
}
.active {
position: relative;
color: #fff;
font-weight: 800;
border-radius: 20rpx;
background-color: #ffbb00;
}
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
::v-deep.uni-scroll-view::-webkit-scrollbar {
display: none
}
</style>
代码实现
<template>
<view>
<tags :tablist='category[0].list' :defaultSelectIndex='defaultSelectIndex0' @select='change'></tags>
<tags :tablist='category[1].list' :defaultSelectIndex='defaultSelectIndex1' @select='change'></tags>
<tags :tablist='category[2].list' :defaultSelectIndex='defaultSelectIndex2' @select='change'></tags>
<view class="">{{content}}</view>
</view>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
const defaultSelectIndex0 = ref(0)
const defaultSelectIndex1 = ref(0)
const defaultSelectIndex2 = ref(0)
const content = ref<string>()
const category = ref([
{
list: [
{
id: 1,
title: '全部',
type: 0
},
{
id: 2,
title: '悬疑',
type: 0
},
{
id: 3,
title: '玄幻',
type: 0
},
{
id: 4,
title: '都市',
type: 0
},
{
id: 5,
title: '科幻',
type: 0
},
{
id: 6,
title: '历史',
type: 0
},
{
id: 7,
title: '同人',
type: 0
},
{
id: 8,
title: '仙侠',
type: 0
}
]
},
{
list: [
{
id: 1,
title: '全部',
type: 1
},
{
id: 2,
title: '连载',
type: 1
},
{
id: 3,
title: '完结',
type: 1
},
{
id: 4,
title: '今日更新',
type: 1
}
]
},
{
list: [
{
id: 1,
title: '全部',
type: 2
},
{
id: 2,
title: '10万字一下',
type: 2
},
{
id: 3,
title: '10万~20万',
type: 2
},
{
id: 4,
title: '20万~30万',
type: 2
},
{
id: 5,
title: '30万~40万',
type: 2
},
{
id: 6,
title: '40万字以上',
type: 2
}
]
},
])
const change = (value, index) => {
if (value.type === 0) {
defaultSelectIndex0.value = index
defaultSelectIndex1.value = 0
defaultSelectIndex2.value = 0
} else if (value.type === 1) {
defaultSelectIndex1.value = index
defaultSelectIndex2.value = 0
} else if (value.type === 2) {
defaultSelectIndex2.value = index
}
}
watch(() => [ defaultSelectIndex0.value, defaultSelectIndex1.value, defaultSelectIndex2.value], () => {
content.value ='发送网络请求:'+category.value[0].list[defaultSelectIndex0.value].title
+ category.value[1].list[defaultSelectIndex1.value].title
+ category.value[2].list[defaultSelectIndex2.value].title
console.log(12121);
}, {
immediate: true
})
</script>
<style>
</style>