uni.setTabBarBadge的text参数必须为字符串(如'1'、'0'、'99+'),数字类型会静默失败;清除数字角标用uni.removeTabBarBadge,隐藏红点用uni.hideTabBarRedDot;自定义Tabbar不支持该API,需自行实现;调用时机应避开onLoad,改用onShow加延时;index从0开始。

uni.setTabBarBadge 的 text 参数必须是字符串
传 1 或 0 这类数字会静默失败,真机上完全没反应。必须写成 '1'、'0' 或 '99+'。尤其在从接口取数后直接拼进 API 时,容易漏掉 String() 转换——比如 res.data.unreadCount 是 number 类型,直接传给 text 就废了。
常见错误写法:uni.setTabBarBadge({ index: 1, text: res.data.unreadCount })
正确写法:uni.setTabBarBadge({ index: 1, text: String(res.data.unreadCount || 0) })
未读数为 0 时该用 remove 还是 hide?
uni.removeTabBarBadge 和 uni.hideTabBarRedDot 不是一回事,也不能互相替代:
- 数字角标用
uni.removeTabBarBadge清除,不是hide - 红点用
uni.hideTabBarRedDot隐藏,不是remove - 如果之前调过
uni.showTabBarRedDot,又想切回数字,得先uni.hideTabBarRedDot,再uni.setTabBarBadge - 如果之前是数字,现在要显示红点(比如未读数 > 99),得先
uni.removeTabBarBadge,再uni.showTabBarRedDot
自定义 Tabbar 上不能用 uni.setTabBarBadge
这个 API 只对 pages.json 里配置的「原生 tabBar」生效。你在 CustomTabbar.vue 里写 uni.setTabBarBadge,真机上一定没反应——不是代码错,是压根不走这条路。
自定义 Tabbar 的红点/数字必须自己画:
- 用
<view class="red-dot"></view>+ CSS 绝对定位 - 偏移建议用
transform: translate(50%, -50%)锚定图标右上角,再微调right: 4px; top: 4px - 状态靠 Pinia store 统一管理,比如
tabBadges.message,所有页面只读不写 - 清空逻辑统一判
=== 0,别用null或undefined当“无角标”
真机测试前必须卡死的三个时机点
很多“本地能跑,真机没效果”的问题,根源不在逻辑,而在调用时机:
-
onLoad阶段调用大概率失败,原生 tabBar 还没渲染完;改用onShow+setTimeout(() => {}, 300)(iOS 更敏感,建议 ≥300ms) - 连续快速更新(比如 WebSocket 批量推送),iOS 容易残留或闪烁;加个简单防抖:
clearTimeout(this.badgeTimer); this.badgeTimer = setTimeout(() => { /* 更新逻辑 */ }, 50) - 下标
index从 0 开始,但 UI 上第一个 tab 常被误认为是第 1 个——写成index: 1实际改的是第二个 tab
红点位置和显隐逻辑本身不复杂,难的是各平台原生控件对 badge 的私有渲染规则不一致,以及状态分散导致的跨页不同步。把更新动作收口到 store,把调用时机卡准,比堆技巧更重要。


















