编写一个 Tab 切换组件是 Vue 中常见的需求,主要涉及动态渲染和状态管理。以下是设计思路和实现步骤:
设计思路
- 组件结构:
Tabs
组件:外层容器,管理当前选中的 Tab。Tab
组件:单个 Tab 项,包含标题和内容。
- 数据驱动:
- 使用
props
传递 Tab 数据(如标题和内容)。 - 使用
v-model
或v-on
实现 Tab 切换。
- 使用
- 动态渲染:
- 根据当前选中的 Tab,动态渲染对应的内容。
- 样式与交互:
- 使用 CSS 实现 Tab 的选中状态样式。
- 支持点击切换 Tab。
实现步骤
1. 创建 Tabs
组件
Tabs
组件负责管理当前选中的 Tab 和渲染子组件。
<template>
<div class="tabs">
<div class="tabs-header">
<!-- 渲染 Tab 标题 -->
<div
v-for="(tab, index) in tabs"
:key="index"
:class="['tab-header-item', { active: index === activeIndex }]"
@click="changeTab(index)"
>
{{ tab.title }}
</div>
</div>
<div class="tabs-content">
<!-- 渲染当前选中的 Tab 内容 -->
<slot :name="`tab-${activeIndex}`"></slot>
</div>
</div>
</template>
<script>
export default {
props: {
tabs: {
type: Array,
required: true,
},
initialIndex: {
type: Number,
default: 0,
},
},
data() {
return {
activeIndex: this.initialIndex, // 当前选中的 Tab 索引
};
},
methods: {
changeTab(index) {
this.activeIndex = index; // 切换 Tab
},
},
};
</script>
<style scoped>
.tabs-header {
display: flex;
border-bottom: 1px solid #ccc;
}
.tab-header-item {
padding: 10px 20px;
cursor: pointer;
}
.tab-header-item.active {
border-bottom: 2px solid #42b983;
font-weight: bold;
}
.tabs-content {
padding: 20px;
}
</style>
2. 使用 Tabs
组件
在父组件中使用 Tabs
组件,并传递 Tab 数据。
<template>
<div>
<Tabs :tabs="tabs" :initialIndex="0">
<!-- 使用具名插槽渲染 Tab 内容 -->
<template v-slot:tab-0>
<div>这是 Tab 1 的内容</div>
</template>
<template v-slot:tab-1>
<div>这是 Tab 2 的内容</div>
</template>
<template v-slot:tab-2>
<div>这是 Tab 3 的内容</div>
</template>
</Tabs>
</div>
</template>
<script>
import Tabs from './Tabs.vue';
export default {
components: {
Tabs,
},
data() {
return {
tabs: [
{ title: 'Tab 1' },
{ title: 'Tab 2' },
{ title: 'Tab 3' },
],
};
},
};
</script>
优化与扩展
- 动态 Tab 内容:
- 可以通过
v-for
动态生成 Tab 内容,而不是硬编码。
- 可以通过
- 动画效果:
- 使用 Vue 的
<transition>
组件为 Tab 切换添加动画效果。
- 使用 Vue 的
- 支持路由:
- 将 Tab 切换与 Vue Router 结合,实现路由级别的 Tab 切换。
- 响应式设计:
- 使用 CSS 媒体查询或 Flexbox/Grid 布局,使 Tab 组件适配移动端。
完整代码示例
以下是完整的 Tabs
组件和父组件的代码:
Tabs.vue
<template>
<div class="tabs">
<div class="tabs-header">
<div
v-for="(tab, index) in tabs"
:key="index"
:class="['tab-header-item', { active: index === activeIndex }]"
@click="changeTab(index)"
>
{{ tab.title }}
</div>
</div>
<div class="tabs-content">
<slot :name="`tab-${activeIndex}`"></slot>
</div>
</div>
</template>
<script>
export default {
props: {
tabs: {
type: Array,
required: true,
},
initialIndex: {
type: Number,
default: 0,
},
},
data() {
return {
activeIndex: this.initialIndex,
};
},
methods: {
changeTab(index) {
this.activeIndex = index;
},
},
};
</script>
<style scoped>
.tabs-header {
display: flex;
border-bottom: 1px solid #ccc;
}
.tab-header-item {
padding: 10px 20px;
cursor: pointer;
}
.tab-header-item.active {
border-bottom: 2px solid #42b983;
font-weight: bold;
}
.tabs-content {
padding: 20px;
}
</style>
App.vue
<template>
<div>
<Tabs :tabs="tabs" :initialIndex="0">
<template v-slot:tab-0>
<div>这是 Tab 1 的内容</div>
</template>
<template v-slot:tab-1>
<div>这是 Tab 2 的内容</div>
</template>
<template v-slot:tab-2>
<div>这是 Tab 3 的内容</div>
</template>
</Tabs>
</div>
</template>
<script>
import Tabs from './Tabs.vue';
export default {
components: {
Tabs,
},
data() {
return {
tabs: [
{ title: 'Tab 1' },
{ title: 'Tab 2' },
{ title: 'Tab 3' },
],
};
},
};
</script>
总结
通过 Vue 的动态渲染和状态管理,可以轻松实现一个 Tab 切换组件。通过插槽和 props,组件可以灵活扩展,满足不同的业务需求。
THE END
暂无评论内容