自定义 TabBar
项目通过 custom: true 开启微信小程序自定义 TabBar 模式,用 Wot Design Uni 的 wd-tabbar 组件替代原生底部导航栏,实现主题联动和灵活定制。
实现原理
自定义 TabBar 涉及三个文件:
| 文件 | 职责 |
|---|---|
pages.config.ts | 声明 TabBar 页面列表,设置 custom: true |
src/layouts/tabbar.vue | 渲染 wd-tabbar 组件,处理页面切换和主题注入 |
src/composables/useTabbar.ts | TabBar 状态管理(徽标数字、激活切换,可选) |
配置页面列表
pages.config.ts 中声明 TabBar 页面,custom: true 开启自定义模式:
ts
// pages.config.ts
export default defineUniPages({
tabBar: {
custom: true, // 开启自定义 TabBar
height: "0", // 原生 TabBar 高度设为 0,完全由自定义组件接管
list: [
{ pagePath: "pages/index/index" },
{ pagePath: "pages/work/index" },
{ pagePath: "pages/mine/index" },
],
},
})1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
list 中的 pagePath 决定哪些页面是 TabBar 页面。color、selectedColor 等原生样式配置在自定义模式下不生效,实际颜色由 tabbar.vue 中的 Wot UI 组件控制。
tabbar 布局组件
TabBar 页面在 definePage() 中声明 layout: "tabbar" 即可使用:
vue
<script setup lang="ts">
definePage({
name: "home",
style: { navigationStyle: "custom" },
layout: "tabbar",
})
</script>1
2
3
4
5
6
7
2
3
4
5
6
7
tabbar.vue 组件做了三件事:
- 渲染
wd-tabbar— 底部固定、安全区适配、带边框 - 初始化激活项 — 通过
getCurrentPages()获取当前页面路径,匹配对应的 TabBar 项 - 处理切换 — 调用
uni.switchTab跳转目标页面
vue
<!-- src/layouts/tabbar.vue(核心逻辑) -->
<wd-tabbar
v-model="active"
bordered
safe-area-inset-bottom
fixed
@change="handleTabbarChange"
>
<wd-tabbar-item
v-for="item in tabbarList"
:key="item.name"
:name="item.name"
:title="item.title"
:icon="item.icon"
/>
</wd-tabbar>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TabBar 配置项在组件内定义,name 与页面路径一一对应:
ts
const tabbarList = [
{ name: "/pages/index/index", title: "首页", icon: "home" },
{ name: "/pages/work/index", title: "工作台", icon: "apps" },
{ name: "/pages/mine/index", title: "我的", icon: "user" },
]1
2
3
4
5
2
3
4
5
主题联动
tabbar.vue 通过 useThemeStore 注入主题:
vue
<wd-config-provider
:theme-vars="themeVars"
:theme="theme === 'dark' ? 'dark' : ''"
>
<slot />
<wd-tabbar ... />
</wd-config-provider>1
2
3
4
5
6
7
2
3
4
5
6
7
切换明暗模式时,TabBar 会自动跟随主题变化。
useTabbar composable
composables/useTabbar.ts 提供独立的 TabBar 状态管理,支持徽标数字和激活切换:
ts
import { useTabbar } from "@/composables/useTabbar"
const { tabbarList, activeTabbar, setTabbarItem, setTabbarItemActive } = useTabbar()
// 设置工作台徽标数字
setTabbarItem("work", 5)
// 切换激活项
setTabbarItemActive("mine")
// 重置状态
resetTabbar()1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
| 方法 / 属性 | 说明 |
|---|---|
tabbarList | TabBar 项列表(computed) |
activeTabbar | 当前激活项 |
setTabbarItem(name, value) | 设置徽标数字 |
getTabbarItemValue(name) | 获取徽标数字 |
setTabbarItemActive(name) | 切换激活项 |
resetTabbar() | 重置为默认状态 |
默认配置三个页签:home、work、mine。支持单例模式(默认)和独立实例:
ts
// 独立实例(不共享全局状态)
const tabbar = useTabbar({ singleton: false })1
2
2
新增 / 修改 TabBar 页签
- 在
pages.config.ts的tabBar.list中添加页面路径 - 在
src/layouts/tabbar.vue的tabbarList数组中添加对应项(name与pagePath一致) - 如果使用了
useTabbar,同步修改DEFAULT_TABBAR_ITEMS
常见问题
| 问题 | 原因 | 处理方式 |
|---|---|---|
| TabBar 不显示 | 页面未声明 layout: "tabbar" | 在 definePage() 中添加 layout: "tabbar" |
| TabBar 页签不匹配 | tabbar.vue 中的 name 与 pagePath 不一致 | 确保两边路径完全一致 |
| APP 端出现原生 TabBar | App 端会显示原生 TabBar | tabbar.vue 已内置 uni.hideTabBar() 处理 |
| 激活项不对 | 页面切换后未更新激活状态 | onShow 中已调用 initActive() 重新匹配 |
