必须彻底删除 pages.json 中的 tabBar 配置,否则即使仅留空对象或注释不全,uni-app 仍会预留 50px 占位层导致底部空白或气泡偏移;custom-tab-bar.vue 中气泡需作为 tab-item 子元素绝对定位渲染,避免 transform 缩放,并注意凸起按钮与气泡的 z-index 和安全区兼容性。

pages.json 必须彻底删掉 tabBar 配置
不删干净,custom: true 就是摆设。哪怕只留一个 "tabBar": {} 或注释没删全,uni-app 仍会悄悄预留 50px 占位层——你看到的“底部空白”“气泡位置飘移”,八成是它在作祟。
检查点:
-
pages.json中整个tabBar对象(包括list、color、backgroundColor等所有字段)必须完全删除或整块注释掉 - HBuilderX 不报错,也不会警告,静默失败是常态
- 删之前建议备份原文件,改完重启 HBuilderX 或重新编译小程序
custom-tab-bar.vue 里怎么加数字气泡
气泡不是靠 uni.showToast 或临时弹窗,而是作为 tab 项的固定子元素渲染。关键在于结构嵌套和样式隔离:
- 每个 tab 项用
<view class="tab-item">包裹图标 + 文字 + 气泡 - 气泡用
<view class="badge">{{ count }},count来自 props 或 Pinia store - 气泡绝对定位:
position: absolute; top: -8px; right: -8px; width: 16px; height: 16px; - 避免用
transform: scale()或font-size控制大小——真机上缩放易糊,且 iOS 安全区计算会错乱
示例片段:
<view class="tab-item" v-for="(item, index) in list" :key="index" @click="onTabClick(index)">
<image :src="selected === index ? item.selectedIconPath : item.iconPath" class="icon"/>
<view class="label">{{ item.text }}</view>
<view v-if="item.badge" class="badge">{{ item.badge }}</view>
</view>
凸起按钮 + 气泡共存时的定位陷阱
中间凸起按钮(如 + 号)和带气泡的 tab 项共存时,z-index 和容器高度必须严格对齐,否则气泡会被遮挡或错位:
- 整个自定义 tabBar 容器设为
position: fixed; bottom: 0; left: 0; right: 0; padding-bottom: env(safe-area-inset-bottom, 34px); - 凸起按钮单独抽离为
position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 10; - 气泡的
z-index至少设为2,但不能 ≥ 凸起按钮的z-index - 安卓部分机型
env(safe-area-inset-bottom)返回0,鸿蒙端甚至不支持,fallback 到padding-bottom: 34px更稳
状态同步和跳转必须手动接管
启用 custom: true 后,uni.onTabItemTap 不再触发,uni.switchTab 对非原生 tab 页面会静默失败:
- 当前激活页索引不要读 DOM class,统一存在 Pinia store 或页面 data 中
- 点击 tab 项时,用
uni.getPages().find(page => page.$route.path === item.pagePath)判断是否已在栈中,再决定uni.switchTab还是uni.navigateTo - 气泡数字更新后,需主动调用
this.$forceUpdate()或用响应式数据(如 ref / reactive)驱动重绘,避免 Vue 缓存导致气泡不刷新 - 别依赖
uni.getTabBar()—— H5 端返回undefined,微信小程序也仅在非 custom 模式下有效
最易被忽略的是:气泡数字变化本身不会触发页面跳转逻辑,它只是 UI 状态;你要确保业务侧(比如消息未读数变更)同步触发 store 更新,并通知 tab 组件重 render。


















