uni_app コンポーネントは、タグ、新規タグ フィルタリングを実装し、マルチレベル フィルタリングをサポートし、デフォルト選択、vue3+ts+setup をサポートします。

レンダリング:

主な機能: 選択したタブはコンポーネントの中央に自動的に移動し、デフォルトで選択したタブ番号をサポートし、マルチレベルのリンク フィルタリングをサポートし、データ リクエストを送信します。

参考記事:uni_app コンポーネントはタブのスライド切り替えを実装し、デフォルトの選択をサポートします、vue3+ts+setup_Pinggu Yishao のブログ - 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>

おすすめ

転載: blog.csdn.net/u012941592/article/details/133206996