自定义 Tabbar 导航栏
13:16概述
项目中的 Tabbar 导航栏采用自定义实现方式,基于 uView Pro 的 Tabbar 组件进行定制,支持多种样式配置和交互效果,支持缓存配置。
Tabbar 基本使用
创建 AppTabbar 组件
vue
<script setup lang="ts">
import { $u } from 'uview-pro'
import { ref } from 'vue'
import { useTabbarStore } from '@/stores'
const { tabbarList } = useTabbarStore()
const current = ref<number>(0)
</script>
<template>
<u-tabbar
v-model="current"
:list="tabbarList"
:active-color="$u.color.primary"
/>
</template>在 AppPage.vue 中实现
vue
<script setup lang="ts">
import type { TabbarItem } from 'uview-pro/types/global'
import type { PropType } from 'vue'
import { $u } from 'uview-pro'
import { computed, ref } from 'vue'
defineProps({
showTabbar: {
type: Boolean,
default: false,
},
customStyle: {
type: [String, Object] as PropType<string | Record<string, any>>,
default: '',
},
customClass: {
type: String,
default: '',
},
})
</script>
<template>
<view class="app-container">
<!-- 页面内容 -->
<slot />
<app-tabbar v-if="showTabbar" />
</view>
</template>
<style scoped lang="scss">
.app-container {
width: 100%;
min-height: 100vh;
overflow-y: auto;
background-color: $u-bg-white;
color: $u-main-color;
}
</style>在页面中使用
vue
<template>
<app-page show-tabbar>
<view>页面内容</view>
</app-page>
</template>使用 Store 管理
typescript
// stores/tabbar.ts
import type { TabbarItem } from 'uview-pro/types/global'
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useTabbarStore = defineStore('tabbar', () => {
const activeIndex = ref(0)
const tabbarList = ref<TabbarItem[]>([
{
text: '首页',
iconPath: 'home',
selectedIconPath: 'home-fill',
pagePath: '/pages/home/home',
isDot: true,
},
{
text: '关于',
iconPath: 'account',
selectedIconPath: 'account-fill',
pagePath: '/pages/about/about',
count: 3,
},
])
const setActiveIndex = (index: number) => {
activeIndex.value = index
}
const updateBadge = (index: number, count: number) => {
tabbarList.value[index].count = count
}
const updateIsDot = (index: number, isDot: boolean) => {
tabbarList.value[index].isDot = isDot
}
return {
activeIndex,
tabbarList,
setActiveIndex,
updateBadge,
updateIsDot,
}
}, {
persist: true,
})在组件中使用:
vue
<script setup lang="ts">
import { useTabbarStore } from '@/stores/tabbar'
const { updateBadge, updateIsDot } = useTabbarStore()
// 更新红点状态
const updateMessageDot = (isDot: boolean) => {
updateIsDot(0, isDot)
}
// 更新消息徽章
const updateMessageBadge = (count: number) => {
updateBadge(1, count)
}
</script>常见场景
- 显示消息未读数
- 红点通知
高级用法
带动画的 Tabbar 切换
vue
<style scoped lang="scss">
.tab-item {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&.active {
animation: tabBarPulse 0.3s ease-out;
}
}
@keyframes tabBarPulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1.05);
}
}
</style>Tabbar 与页面过渡
vue
<script setup lang="ts">
import { ref } from 'vue'
const transitionName = ref('slide-fade')
</script>
<template>
<view class="app">
<u-transition :name="transitionName" :appear="true">
<slot />
</u-transition>
<app-tabbar />
</view>
</template>缓存 Tabbar 页面
在 pages.json 中添加如下配置:
json
{
"tabBar": {
"list": [
{
"pagePath": "pages/home/home"
},
{
"pagePath": "pages/about/about"
}
]
}
}最佳实践
- 响应式设计 - 确保 Tabbar 在不同屏幕尺寸上都能正常显示
- 易用性 - Tabbar 项不要超过 5 个,否则文本会太小
- 一致性 - 所有图标应该采用相同的风格和大小
- 反馈 - 为选中状态提供明显的视觉反馈
- 性能 - 避免在 Tabbar 中放置重型组件
- 安全区 - 在底部留出足够空间以适应设备的安全区域
- 测试 - 在不同设备上测试 Tabbar 的显示效果
故障排除
Tabbar 不显示
检查:
- 组件是否正确导入
- CSS 样式是否正确应用
- z-index 是否设置过低
