Skip to content

自定义 Tabbar 导航栏

23:52

概述

项目中的 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"
      }
    ]
  }
}

最佳实践

  1. 响应式设计 - 确保 Tabbar 在不同屏幕尺寸上都能正常显示
  2. 易用性 - Tabbar 项不要超过 5 个,否则文本会太小
  3. 一致性 - 所有图标应该采用相同的风格和大小
  4. 反馈 - 为选中状态提供明显的视觉反馈
  5. 性能 - 避免在 Tabbar 中放置重型组件
  6. 安全区 - 在底部留出足够空间以适应设备的安全区域
  7. 测试 - 在不同设备上测试 Tabbar 的显示效果

故障排除

Tabbar 不显示

检查:

  1. 组件是否正确导入
  2. CSS 样式是否正确应用
  3. z-index 是否设置过低

相关文档