Ver código fonte

refactor(tabbar): 重构自定义底部导航栏组件实现

使用原生 view 组件替代 wd-tabbar 组件实现自定义底部导航栏
添加虚拟宿主选项以优化微信小程序 flex 布局
统一处理点击事件和颜色状态管理
feige996 9 meses atrás
pai
commit
3092d88040
2 arquivos alterados com 56 adições e 29 exclusões
  1. 1 1
      src/tabbar/config.ts
  2. 55 28
      src/tabbar/index.vue

+ 1 - 1
src/tabbar/config.ts

@@ -1,7 +1,7 @@
 import type { TabBar } from '@uni-helper/vite-plugin-uni-pages'
 
 type FgTabBarItem = TabBar['list'][0] & {
-  icon: string
+  icon: any // 其实是 string 类型,这里是为了避免 ts 报错
   iconType: 'uniUi' | 'uiLib' | 'unocss' | 'iconfont' | 'local'
 }
 

+ 55 - 28
src/tabbar/index.vue

@@ -3,9 +3,20 @@
 import { tabbarList as _tabBarList, customTabbarEnable, nativeTabbarNeedHide, tabbarCacheEnable } from './config'
 import { tabbarStore } from './store'
 
+// #ifdef MP-WEIXIN
+// 将自定义节点设置成虚拟的(去掉自定义组件包裹层),更加接近Vue组件的表现,能更好的使用flex属性
+defineOptions({
+  virtualHost: true,
+})
+// #endif
+
 /** tabbarList 里面的 path 从 pages.config.ts 得到 */
 const tabbarList = _tabBarList.map(item => ({ ...item, path: `/${item.pagePath}` }))
-function selectTabBar({ value: index }: { value: number }) {
+function handleClick(index: number) {
+  // 点击原来的不做操作
+  if (index === tabbarStore.curIdx) {
+    return
+  }
   const url = tabbarList[index].path
   tabbarStore.setCurIdx(index)
   if (tabbarCacheEnable) {
@@ -27,37 +38,53 @@ onLoad(() => {
     },
   })
 })
+const activeColor = '#1890ff'
+const inactiveColor = '#666'
+function getColorByIndex(index: number) {
+  return tabbarStore.curIdx === index ? activeColor : inactiveColor
+}
 </script>
 
 <template>
-  <wd-tabbar
-    v-if="customTabbarEnable"
-    v-model="tabbarStore.curIdx"
-    bordered
-    safe-area-inset-bottom
-    placeholder
-    fixed
-    @change="selectTabBar"
-  >
-    <block v-for="(item, idx) in tabbarList" :key="item.path">
-      <wd-tabbar-item v-if="item.iconType === 'uiLib'" :title="item.text" :icon="item.icon" />
-      <wd-tabbar-item
-        v-else-if="item.iconType === 'unocss' || item.iconType === 'iconfont'"
-        :title="item.text"
+  <view v-if="customTabbarEnable" class="flex items-center justify-between">
+    <view class="__content__ border-and-fixed h-50px flex" @touchmove.stop.prevent>
+      <view
+        v-for="(item, index) in tabbarList" :key="index"
+        class="flex flex-1 flex-col items-center justify-center"
+        :style="{ color: getColorByIndex(index) }"
+        @click="handleClick(index)"
       >
-        <template #icon>
-          <view
-            h-40rpx
-            w-40rpx
-            :class="[item.icon, idx === tabbarStore.curIdx ? 'is-active' : 'is-inactive']"
-          />
+        <template v-if="item.iconType === 'uniUi'">
+          <uni-icons :type="item.icon" size="20" :color="getColorByIndex(index)" />
         </template>
-      </wd-tabbar-item>
-      <wd-tabbar-item v-else-if="item.iconType === 'local'" :title="item.text">
-        <template #icon>
-          <image :src="item.icon" class="h-40rpx w-40rpx" />
+        <template v-if="item.iconType === 'uiLib'">
+          <!-- TODO: 以下内容请根据选择的UI库自行替换 -->
+          <!-- 如:<wd-icon name="home" /> (https://wot-design-uni.cn/component/icon.html) -->
+          <!-- 如:<uv-icon name="home" /> (https://www.uvui.cn/components/icon.html) -->
+          <!-- 如:<sar-icon name="image" /> (https://sard.wzt.zone/sard-uniapp-docs/components/icon)(sar没有home图标^_^) -->
+          <wd-icon :name="item.icon" />
         </template>
-      </wd-tabbar-item>
-    </block>
-  </wd-tabbar>
+        <template v-if="item.iconType === 'unocss' || item.iconType === 'iconfont'">
+          <view :class="item.icon" />
+        </template>
+        <view class="text-12px">
+          {{ item.text }}
+        </view>
+      </view>
+      <view class="pb-safe" />
+    </view>
+    <view class="__placeholder__ h-50px" />
+  </view>
 </template>
+
+<style scoped lang="scss">
+.border-and-fixed {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+
+  border-top: 1px solid #eee;
+  box-sizing: border-box;
+}
+</style>