vue 实现tabs
Vue 实现 Tabs 组件的方法
基础实现
创建一个基础的 Tabs 组件需要定义两个子组件:Tabs 和 Tab。Tabs 作为容器,Tab 作为内容项。
Tabs.vue
<template>
<div class="tabs">
<div class="tabs-header">
<button
v-for="(tab, index) in tabs"
:key="index"
@click="selectTab(index)"
:class="{ active: index === activeIndex }"
>
{{ tab.props.title }}
</button>
</div>
<div class="tabs-content">
<slot></slot>
</div>
</div>
</template>
<script>
import { ref, provide, computed } from 'vue'
export default {
setup() {
const tabs = ref([])
const activeIndex = ref(0)
const selectTab = (index) => {
activeIndex.value = index
}
provide('tabsContext', {
tabs,
activeIndex
})
return {
tabs,
activeIndex,
selectTab
}
}
}
</script>
Tab.vue
<template>
<div v-show="isActive">
<slot></slot>
</div>
</template>
<script>
import { inject, computed, onMounted } from 'vue'
export default {
props: {
title: {
type: String,
required: true
}
},
setup(props) {
const { tabs, activeIndex } = inject('tabsContext')
const isActive = computed(() => {
return tabs.value[activeIndex.value] === instance
})
const instance = { props }
onMounted(() => {
tabs.value.push(instance)
})
return {
isActive
}
}
}
</script>
使用示例
<template>
<Tabs>
<Tab title="Tab 1">
Content for Tab 1
</Tab>
<Tab title="Tab 2">
Content for Tab 2
</Tab>
<Tab title="Tab 3">
Content for Tab 3
</Tab>
</Tabs>
</template>
<script>
import Tabs from './Tabs.vue'
import Tab from './Tab.vue'
export default {
components: {
Tabs,
Tab
}
}
</script>
进阶功能
动态添加/删除 Tab
可以通过修改 tabs 数组来实现动态添加或删除 Tab。在 Tabs 组件中暴露添加和删除的方法:
// 在 Tabs.vue 的 setup 中添加
const addTab = (tab) => {
tabs.value.push(tab)
}
const removeTab = (index) => {
tabs.value.splice(index, 1)
if (activeIndex.value >= tabs.value.length) {
activeIndex.value = tabs.value.length - 1
}
}
provide('tabsContext', {
tabs,
activeIndex,
addTab,
removeTab
})
动画效果 可以为 Tab 切换添加过渡动画:
<template>
<transition name="fade" mode="out-in">
<div v-show="isActive">
<slot></slot>
</div>
</transition>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
路由集成 可以与 Vue Router 集成,使每个 Tab 对应一个路由:
// 在 Tabs.vue 中
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
// 根据路由路径设置 activeIndex
const updateActiveIndex = () => {
const index = tabs.value.findIndex(tab => tab.props.to === route.path)
if (index !== -1) {
activeIndex.value = index
}
}
// Tab 点击时导航到对应路由
const selectTab = (index) => {
const tab = tabs.value[index]
if (tab.props.to) {
router.push(tab.props.to)
}
activeIndex.value = index
}
样式定制
可以通过 CSS 变量或 props 来自定义样式:

<template>
<div class="tabs" :style="{
'--active-color': activeColor,
'--inactive-color': inactiveColor
}">
<!-- ... -->
</div>
</template>
<script>
export default {
props: {
activeColor: {
type: String,
default: '#42b983'
},
inactiveColor: {
type: String,
default: '#2c3e50'
}
}
}
</script>
<style>
.tabs-header button.active {
color: var(--active-color);
border-bottom: 2px solid var(--active-color);
}
.tabs-header button {
color: var(--inactive-color);
}
</style>






