在 UniApp + Vue3 中实现自定义 tabBar
原生 tabBar 往往无法满足复杂的 UI 需求,通过自定义 tabBar 可以完全掌控样式和交互。但在实现时,需要注意页面栈的管理,避免内存溢出。
1. 基础配置
首先在 pages.json 中启用自定义 tabBar。虽然启用了 custom,但建议保留 tabBar 的 list 结构定义。这样做是为了利用 uni-app 底层的跳转机制,防止因频繁调用 navigateTo 导致页面栈无限增长。
如果连续点击切换,页面栈会迅速膨胀,增加崩溃风险。
{
"tabBar": {
"custom": true,
"list": [
{
"pagePath": "pages/study/study",
"text": "学习"
},
{
"pagePath": "pages/mood/mood",
"text": "情绪"
}
]
}
}
2. 组件开发
创建一个独立的 tabBar 组件。为了便于维护,建议使用 v-for 遍历列表数据。这里的关键是接收父组件传来的当前索引(currentIndex),用于判断高亮状态。
<script setup>
import { ref } from 'vue'
const props = defineProps({
currentIndex: Number
})
// 定义 Tab 列表,需与 pages.json 保持一致
const tabBarList = ref([
{ pagePath: 'pages/study/study', text: '学习' },
{ pagePath: 'pages/mood/mood', text: '情绪' },
{ pagePath: 'pages/friend/friend', text: '研友' },
{ pagePath: 'pages/AI/AI', text: '芯研' },
{ pagePath: 'pages/my/my', text: '我的' }
])
// 处理点击事件,使用 switchTab 保证页面栈安全
const handleItemClick = (index) => {
uni.switchTab({
url: '/' + tabBarList.value[index].pagePath
})
}
</script>
<template>
<view class="container">
<view
v-for="(item, index) in tabBarList"
:key="index"
class="item"
@click="handleItemClick(index)"
>
<image
src="@/static/tabBar/学习.png"
style="width: 62rpx; height: 52rpx;"
/>
<view>{{ item.text }}</view>
<!-- 根据索引控制高亮色块 -->
<view class="circle" v-show="props.currentIndex === index"></view>
</view>
</view>
</template>
<style lang="scss" scoped>
.container {
width: 100%;
position: fixed !important;
bottom: 0rpx;
display: flex;
justify-content: space-evenly;
padding-bottom: 40rpx;
background-color: white;
z-index: 99999;
.item {
display: flex;
flex-direction: column;
gap: 10rpx;
align-items: center;
position: relative;
.circle {
position: absolute;
top: -10rpx;
left: 10rpx;
width: 50rpx;
height: 50rpx;
background: rgba(255, 219, 217, 0.54);
border-radius: 50%;
}
}
}
</style>


