El componente uni_app implementa el cambio deslizante de pestañas, admite la selección predeterminada, vue3 + ts + setup

Captura de pantalla del efecto:

Prefacio:

Recientemente, al desarrollar programas pequeños, necesito usar el componente de pestañas. Cuando hay muchas pestañas, puedes deslizarlas hacia la izquierda y hacia la derecha. Encontré uView UI en la biblioteca de complementos, pero el tamaño del complemento de esta biblioteca no es demasiado pequeño. El mini programa necesita reducir el tamaño del paquete tanto como sea posible, por lo que planeo empaquetarlo yo mismo.

Capacidades principales: la pestaña seleccionada se moverá automáticamente a la posición media del componente. Admite la pestaña seleccionada de forma predeterminada. Puede obtener datos junto con el deslizador. Admite el uso junto con el deslizador.

Método principal: vista de desplazamiento

scroll-x:true //允许横向滚动

scroll-left //设置横向滚动条位置

scroll-with-animation  //在设置滚动条位置时使用动画过渡

Los accesorios de parámetros aceptados por las pestañas, tablist es la matriz de pestañas pasada por el componente principal y defaultsSelectIndex es el número de pestañas seleccionadas de forma predeterminada.

<tabs :tablist='list' :defaultSelectIndex='defaultSelectIndex' @select='change'></tabs>

Calcular el ancho de cada pestaña.

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()


	})

El método utilizado por select para exponer la pestaña seleccionada al componente principal.

const emits=defineEmits<{
		(e : 'select',value : ItabItem) : void
	}>()

Ocultar control deslizante

/* 隐藏滚动条*/
	::v-deep.uni-scroll-view::-webkit-scrollbar {
		display: none
	}

Código de implementación del componente tabs.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
	}
	interface Iprops {
		tablist : Array<ItabItem>
		defaultSelectIndex ?: number
	}
    
	const props = withDefaults(defineProps<Iprops>(), {
		tablist: () => [],
		defaultSelectIndex: 6
	})
	const emits=defineEmits<{
		(e : 'select',value : ItabItem) : 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])
	}
	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 {

		background-color: rgba(0, 0, 0, .1);
		position: fixed;
		z-index: 99;
		width: 100%;
		align-items: center;
		height: 100rpx;

		.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-bottom: 10px;
					display: flex;
					justify-content: center;
					font-size: 16px;
					padding-top: 10px;
				}
			}
		}
	}


	.active {
		position: relative;
		color: #333;
		font-weight: 800;
	}

	.active::after {
		content: "";
		position: absolute;
		width: 40rpx;
		height: 8rpx;
		border-radius: 8rpx;
		background-color: #333;
		left: 0px;
		right: 0px;
		bottom: 0px;
		margin: auto;
	}

	/* 隐藏滚动条,但依旧具备可以滚动的功能 */
	::v-deep.uni-scroll-view::-webkit-scrollbar {
		display: none
	}
</style>

Uso index.vue

<template>
	<view>
		<text style="text-align: center;width: 100%;display: block;"> 标题</text>
		<tabs :tablist='list' :defaultSelectIndex='defaultSelectIndex' @select='change'></tabs>
	</view>
	<button @click="add" style="margin-top: 100rpx;">父组件调用切换</button>
	
</template>

<script lang="ts" setup>
	import { ref } from "vue";
	const defaultSelectIndex=ref(0)
	const list = ref([
		
		{
			id: 1,
			title: '直播直播',
		},
		{
			id: 2,
			title: '热门推荐',
		},
		{
			id: 3,
			title: '音乐',
		},
		{
			id: 4,
			title: '经典小说',
		},
		{
			id: 5,
			title: '看书',
		},
		{
			id: 6,
			title: '短剧',
		},
		{
			id: 7,
			title: '相声评述',
		},
		{
			id: 8,
			title: '找书广场',
		},
	])
    const change=(value)=>{
		uni.showToast({
			title: value.title,
			duration: 2000
		});

	}
	const add=( )=>{
		defaultSelectIndex.value++
	}
</script>

<style>

</style>

Espero que este artículo te sea útil. También lo encapsulé según mis propias necesidades. También puedes optimizar el código según tus propias necesidades.

Supongo que te gusta

Origin blog.csdn.net/u012941592/article/details/133153866
Recomendado
Clasificación