Vue3封装tabs切换组件

效果如下:

代码如下:

<template>
	<div class="tabs-container">
		<div class="tabs-header">
			<div v-for="tab in tabs" :key="tab.name" class="tab" @click="handleTabClick(tab)" ref="tabRefs" :data-tab-name="tab.name">
				{{ tab.name }}
			</div>
			<div class="slider" :style="sliderStyle"></div>
		</div>
	</div>
</template>

<script setup>
import { ref, computed } from "vue";

const props = defineProps({
	tabs: {
		type: Array,
		required: true
	},
	defaultActive: {
		type: String,
		default: ""
	}
});
const activeTab = ref(props.defaultActive || props.tabs[0].name);
const tabRefs = ref([]);

const getActiveTabElement = () => {
	return tabRefs.value.find(tab => tab.dataset.tabName === activeTab.value);
};

const sliderStyle = computed(() => {
	const activeTabElement = getActiveTabElement();
	if (activeTabElement) {
		const { offsetLeft, offsetWidth } = activeTabElement;
		return {
			transform: `translateX(${offsetLeft}px)`,
			width: `${offsetWidth}px`
		};
	}
	return {};
});

const emit = defineEmits(["change"]);
const handleTabClick = tab => {
	if (activeTab.value !== tab.name) {
		activeTab.value = tab.name;
		emit("change", tab);
	}
};
</script>

<style lang="scss" scoped>
.tabs-container {
	position: relative;
	user-select: none;
	background: rgb(255 255 255 / 20%);
	border-radius: 30px;
	display: inline-block;
	overflow: hidden;
}
.tabs-header {
	display: flex;
	position: relative;
}
.tab {
	padding: 4px 12px;
	cursor: pointer;
	position: relative;
	color: #ffffff;
	font-weight: 500;
	font-size: 14px;
	z-index: 999;
}
.slider {
	position: absolute;
	bottom: 0;
	height: 100%;
	background-color: #2578f2;
	transition: transform 0.3s ease, width 0.3s ease;
	border-radius: 30px;
}
.tabs-content {
	padding: 10px;
}
</style>

使用方式:

<template>
	<Tabs :tabs="tabsList" @change="tabChange"></Tabs>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Tabs from "@/components/Tabs/index.vue";
interface IInfo {
	id: number;
	name: string;
}
const tabsList = ref<Array<IInfo>>([
	{
		id: 1,
		name: "标签1"
	},
	{
		id: 2,
		name: "标签2"
	},
	{
		id: 3,
		name: "标签3"
	}
]);
const tabChange = (info: IInfo) => {
	console.log(info);
};
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值