index.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <template>
  2. <view class="custom-tabbar">
  3. <view class="tabbar-border"></view>
  4. <view class="tabbar-list">
  5. <view
  6. v-for="(item, index) in tabList"
  7. :key="index"
  8. class="tabbar-item"
  9. @click="handleNavigate(item.path)"
  10. >
  11. <image
  12. class="tab-icon"
  13. :src="isPathActive(item.path) ? item.activeIcon : item.icon"
  14. mode="aspectFit"
  15. ></image>
  16. <view
  17. class="tab-text"
  18. :class="{ 'tab-text-active': isPathActive(item.path) }"
  19. >
  20. {{ item.text }}
  21. </view>
  22. </view>
  23. </view>
  24. </view>
  25. </template>
  26. <script setup>
  27. import { ref, onMounted } from 'vue'
  28. import tabListData from '@/json/tabbar.json'
  29. // 底部列表数据
  30. const tabList = ref(tabListData || [])
  31. // 当前页面路径
  32. const currentRoute = ref('')
  33. /**
  34. * 组件挂载时自动识别当前所在路径
  35. */
  36. onMounted(() => {
  37. const pages = getCurrentPages()
  38. if (pages.length > 0) {
  39. const route = pages[pages.length - 1].route
  40. // 统一补齐前缀斜杠,方便与 tabbar.json 匹配
  41. currentRoute.value = route.startsWith('/') ? route : '/' + route
  42. }
  43. })
  44. /**
  45. * 判断路径是否匹配(高亮逻辑)
  46. */
  47. const isPathActive = (path) => {
  48. if (!path || !currentRoute.value) return false
  49. // 格式化对比路径
  50. const targetPath = path.startsWith('/') ? path : '/' + path
  51. const currentPath = currentRoute.value.startsWith('/') ? currentRoute.value : '/' + currentRoute.value
  52. return currentPath === targetPath
  53. }
  54. /**
  55. * 页面跳转逻辑
  56. */
  57. const handleNavigate = (path) => {
  58. const targetUrl = path.startsWith('/') ? path : '/' + path
  59. // 如果已经是当前页,则不重复跳转
  60. if (isPathActive(targetUrl)) return
  61. // 由于 pages.json 中没有 tabBar 配置,
  62. // 使用 reLaunch 跳转能保证页面栈清空,模拟 TabBar 行为
  63. uni.reLaunch({
  64. url: targetUrl,
  65. fail: (err) => {
  66. console.error('跳转失败:', err)
  67. }
  68. })
  69. }
  70. </script>
  71. <style lang="scss" scoped>
  72. .custom-tabbar {
  73. position: fixed;
  74. bottom: 0;
  75. left: 0;
  76. width: 100%;
  77. height: calc(110rpx + env(safe-area-inset-bottom));
  78. background-color: #ffffff;
  79. display: flex;
  80. flex-direction: column;
  81. z-index: 9999;
  82. padding-bottom: env(safe-area-inset-bottom);
  83. box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.05);
  84. }
  85. .tabbar-border {
  86. height: 1px;
  87. background-color: rgba(0, 0, 0, 0.06);
  88. transform: scaleY(0.5);
  89. }
  90. .tabbar-list {
  91. display: flex;
  92. flex: 1;
  93. align-items: center;
  94. justify-content: space-around;
  95. padding: 0 10rpx;
  96. }
  97. .tabbar-item {
  98. display: flex;
  99. flex-direction: column;
  100. align-items: center;
  101. justify-content: center;
  102. flex: 1;
  103. height: 100%;
  104. &:active {
  105. opacity: 0.7;
  106. }
  107. }
  108. .tab-icon {
  109. width: 48rpx;
  110. height: 48rpx;
  111. margin-bottom: 4rpx;
  112. }
  113. .tab-text {
  114. font-size: 20rpx;
  115. color: #999999;
  116. transition: all 0.2s;
  117. &.tab-text-active {
  118. color: #f7ca3e;
  119. font-weight: bold;
  120. }
  121. }
  122. </style>