cwg-tab-bar.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <template>
  2. <nav v-if="showBar" class="custom-tabbar">
  3. <div v-for="item in tabs" :key="item.path" class="tabbar-item" :class="[{ active: route.path === item.path }]"
  4. @click="onTabClick(item.path)">
  5. <span class="tabbar-icon">
  6. <cwg-icon :name="item.icon" :color="route.path === item.path ? '#ea002a' : '#000'" />
  7. </span>
  8. <span class="tabbar-label">{{ t(item.label) }}</span>
  9. </div>
  10. </nav>
  11. </template>
  12. <script setup lang="ts">
  13. import { computed, watch, onMounted, ref } from 'vue'
  14. import { useI18n } from 'vue-i18n'
  15. import useRouter from "@/hooks/useRouter";
  16. import useRoute from '@/hooks/useRoute'
  17. const { t } = useI18n()
  18. const router = useRouter()
  19. const route = useRoute()
  20. // 定义 emits
  21. const emit = defineEmits<{
  22. (e: 'update:isTabBarPage', value: boolean): void
  23. }>()
  24. const tabBarPages = [
  25. '/pages/card/index',
  26. '/pages/wallet/index',
  27. '/pages/mine/index',
  28. ]
  29. const showBar = computed(() => {
  30. // 不显示返回按钮的页面
  31. const noBarPages = [
  32. '/pages/card/index',
  33. '/pages/wallet/index',
  34. '/pages/mine/index',
  35. ]
  36. return noBarPages.includes(route.path)
  37. })
  38. // 计算当前页面是否是 tab 页面
  39. const isTabBarPage = computed(() => {
  40. return tabBarPages.includes(route.path)
  41. })
  42. // 监听路由变化,向父组件传递是否是 tab 页面的状态
  43. watch(route, () => {
  44. emit('update:isTabBarPage', isTabBarPage.value)
  45. }, { immediate: true })
  46. const tabs = ref([
  47. {
  48. label: 'tabs.cards',
  49. path: '/pages/card/index',
  50. icon: 'icon_card',
  51. },
  52. {
  53. label: 'tabs.wallet',
  54. path: '/pages/wallet/index',
  55. icon: 'icon_wallet',
  56. },
  57. {
  58. label: 'tabs.mine',
  59. path: '/pages/mine/index',
  60. icon: 'icon_my',
  61. },
  62. ])
  63. function onTabClick(path: string) {
  64. if (route.path !== path) {
  65. router.replace(path)
  66. }
  67. }
  68. // 组件挂载时也触发一次
  69. onMounted(() => {
  70. emit('update:isTabBarPage', isTabBarPage.value)
  71. })
  72. </script>
  73. <style scoped lang="scss">
  74. @import "@/uni.scss";
  75. .custom-tabbar {
  76. position: fixed;
  77. left: 0;
  78. right: 0;
  79. bottom: 0;
  80. height: px2rpx(60);
  81. background: var(--main-bg);
  82. border-radius: 18px 18px 0 0;
  83. display: flex;
  84. justify-content: space-around;
  85. align-items: center;
  86. box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.12);
  87. z-index: 100;
  88. margin: 0 px2rpx(8) px2rpx(0) px2rpx(8);
  89. }
  90. .tabbar-item {
  91. flex: 1;
  92. display: flex;
  93. flex-direction: column;
  94. align-items: center;
  95. justify-content: center;
  96. color: var(--white);
  97. font-size: var(--font-size-12);
  98. font-weight: 600;
  99. border-radius: 12px;
  100. line-height: px2rpx(16);
  101. padding: px2rpx(8) 0;
  102. cursor: pointer;
  103. }
  104. .tabbar-item.active {
  105. color: var(--main-yellow);
  106. }
  107. .tabbar-icon {
  108. margin-bottom: px2rpx(4);
  109. font-size: var(--font-size-24);
  110. }
  111. .tabbar-icon-active {
  112. color: var(--main-yellow);
  113. }
  114. .tabbar-label {
  115. font-weight: 500;
  116. line-height: 1.2;
  117. letter-spacing: px2rpx(1);
  118. }
  119. </style>