ant-design Badge 徽标数组件完全指南:API 详解、源码原理与实战应用
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
Badge(徽标数)是 ant-design 数据展示组件家族中最常用的组件之一,通常出现在通知图标或头像的右上角,用于展示待处理消息条数、未读标记或状态信号。本文基于当前仓库 components/badge 目录下的官方中文文档与源码实现,系统讲解 Badge 的全部 API、核心交互行为(封顶、溢出、滚动动画、状态点、缎带等)及其底层实现原理,帮助你在实际项目中熟练使用并知其所以然。
何时使用
一般出现在通知图标或头像的右上角,用于显示需要处理的消息条数,通过醒目视觉形式吸引用户处理。典型场景包括:
- 导航栏/侧边栏的通知入口,展示未读消息数量;
- 头像右上角展示待办数量或在线状态;
- 列表项右侧展示待处理事项的数量标记;
- 卡片或内容区域用状态点(success/error/warning)表达业务状态。
快速上手
Badge 作为独立组件从antd包中导出,最简单的用法是包裹一个子元素并传入count:
import { Badge, Avatar } from 'antd'; const App: React.FC = () => ( <Badge count={5}> <Avatar shape="square" size="large" /> </Badge> );完整可运行示例可参考仓库中的 基本用法演示,其中还演示了count={0} showZero强制展示零值,以及把count直接传一个 ReactNode(如<ClockCircleOutlined />)实现自定义图标徽标的能力。
Badge API
通用属性参考:通用属性。Badge 组件对外暴露的核心属性如下表:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| color | 自定义小圆点的颜色 | string | - | |
| count | 展示的数字,大于 overflowCount 时显示为${overflowCount}+,为 0 时隐藏 | ReactNode | - | |
| classNames | 语义化结构 class | Record<SemanticDOM, string> | - | 5.7.0 |
| dot | 不展示数字,只有一个小红点 | boolean | false | |
| offset | 设置状态点的位置偏移 | [number, number] | - | |
| overflowCount | 展示封顶的数字值 | number | 99 | |
| showZero | 当数值为 0 时,是否展示 Badge | boolean | false | |
| size | 在设置了count的前提下有效,设置小圆点的大小 | default|small | - | - |
| status | 设置 Badge 为状态点 | success|processing|default|error|warning | - | |
| styles | 语义化结构 style | Record<SemanticDOM, CSSProperties> | - | 5.7.0 |
| text | 在设置了status的前提下有效,设置状态点的文本 | ReactNode | - | |
| title | 设置鼠标放在状态点上时显示的文字 | string | - |
核心属性详解
count(展示的数字):默认值为null(源码中count = null,见 index.tsx)。计数逻辑遵循三条规则:
- 大于
overflowCount时显示为${overflowCount}+; - 为 0 时隐藏(除非设置
showZero); - 传入
ReactNode时直接渲染自定义内容,例如 basic.tsx 中传入<ClockCircleOutlined style={{ color: '#f5222d' }} />。
从源码看(index.tsx),展示值由numberedDisplayCount计算:count > overflowCount ? \${overflowCount}+` : count,随后isZero、ignoreCount、isHidden等布尔量共同决定徽标是否渲染。特别地,负数和字符串数字(如-10、"-10"、"3.5"`)也能正确展示,测试用例见 index.test.tsx 与 index.test.tsx。
overflowCount(封顶数字值):默认99,当 count 超过该值时显示${overflowCount}+。参考 封顶数字演示:
<Badge count={99} /> <Badge count={100} /> {/* 显示 99+ */} <Badge count={99} overflowCount={10} /> {/* 显示 10+ */} <Badge count={1000} overflowCount={999} /> {/* 显示 999+ */}dot(小红点):设置为true时不展示数字,只显示一个小红点。参考 讨嫌的小红点演示。注意两个边界行为(源码与测试均已覆盖):dot在count为 0 时不展示(showAsDot = dot && !isZero,见 index.tsx),且 dot 模式下不会因为位数多而加宽为“多字符胶囊”样式,测试见 index.test.tsx。
showZero(是否展示零值):默认false,即count={0}时徽标整体隐藏。设置为true后可展示数字 0,参考 basic.tsx 中的<Badge count={0} showZero>。
size(徽标大小):在设置了count的前提下有效,取值default或small。参考 大小演示。源码中size === 'small'会额外追加${prefixCls}-count-sm样式类(index.tsx),其视觉差异由样式文件定义(见下文主题变量部分)。
offset(位置偏移):类型为[number, number],分别表示水平与垂直偏移。参考 自定义位置偏移演示:
<Badge count={5} offset={[10, 10]}> <Avatar shape="square" size="large" /> </Badge>源码中偏移的实现值得注意(index.tsx):垂直方向通过marginTop: offset[1]实现;水平方向根据ConfigContext中的direction判断——LTR 下设置right = -parseInt(offset[0]),RTL 下设置left = parseInt(offset[0]),从而天然适配从右到左的阅读方向。offset同样支持传入 ReactNode 作为 count 的场景(index.test.tsx)。
status(状态点):取值success|processing|default|error|warning,参考 状态点演示:
<Badge status="success" /> <Badge status="processing" /> <Badge status="error" text="Error" />状态点可搭配text展示文字(如text="Error"),也可单独使用。源码中hasStatus判定(index.tsx)说明:只有当status或color被设置、且count为空(ignoreCount)时,组件才会以“状态点”模式渲染(即根节点只渲染状态圆点与文本,不包裹 children)。其中processing状态带有一个循环扩散的脉冲动画。
title(悬浮提示):设置鼠标悬停在徽标上时显示的文字。默认情况下,若未显式传title,会取当前展示的数值作为 title(index.tsx)。参考 自定义标题演示,测试覆盖见 index.test.tsx。
color(自定义颜色):既可用于数字徽标(count 模式),也可用于状态点。支持两种写法:
- 预设色名:
pink、red、yellow、orange、cyan、green、blue、purple、geekblue、magenta、volcano、gold、lime(完整预设列表见 theme/interface/presetColors.ts); - 任意 CSS 颜色值:
#f50、rgb(...)、hsl(...)、hwb(...)均可。
参考 多彩徽标演示。源码中通过isPresetColor(color, false)(来自 _util/colors.ts)区分预设色与自定义色:预设色走genPresetColor生成的样式类(如.ant-badge-color-red),自定义色则以内联样式background/color直接写入(index.tsx)。
classNames / styles(语义化结构定制,5.7.0+):用于对 Badge 内部结构做细粒度样式定制,详见下文 Semantic DOM。
Badge.Ribbon API
Ribbon(缎带)通过Badge.Ribbon子组件使用,可将一个文本缎带贴在卡片等容器的右上角/左上角:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| color | 自定义缎带的颜色 | string | - | |
| placement | 缎带的位置,start和end随文字方向(RTL 或 LTR)变动 | start|end | end | |
| text | 缎带中填入的内容 | ReactNode | - |
参考 缎带演示:
<Badge.Ribbon text="Hippies"> <Card title="Pushes open the window" size="small"> and raises the spyglass. </Card> </Badge.Ribbon> <Badge.Ribbon text="Hippies" color="pink"> <Card title="Pushes open the window" size="small"> and raises the spyglass. </Card> </Badge.Ribbon>从源码看(Ribbon.tsx),Ribbon 的实现要点:
placement默认'end',渲染类名${prefixCls}-placement-${placement};- 预设色复用
isPresetColor判定生成-color-*类,自定义色直接写入background; - 缎带主体与“折角”(corner)分离渲染:
corner元素通过边框 +badgeRibbonCornerTransform: 'scaleY(0.75)'与badgeRibbonCornerFilter: brightness(75%)实现立体折角效果(见 style/ribbon.ts); - RTL 环境下自动追加
${prefixCls}-rtl类,start/end位置随文字方向对调(Ribbon.tsx)。
Semantic DOM
从 5.7.0 版本开始,Badge 提供语义化 DOM 结构,可通过classNames与styles精确命中内部节点:
| 节点 | 说明 | 版本 |
|---|---|---|
| root | 根节点 | 5.7.0 |
| indicator | 指示器节点(徽标数字/圆点本身) | 5.7.0 |
对应源码中的类型定义(index.tsx):
classNames?: { root?: string; indicator?: string; }; styles?: { root?: React.CSSProperties; indicator?: React.CSSProperties; };参考 语义化结构演示。使用示例:
<Badge count={5} classNames={{ root: 'my-badge-root', indicator: 'my-badge-indicator' }} styles={{ indicator: { background: '#52c41a' } }} > <Avatar shape="square" size="large" /> </Badge>源码中,classNames.root与styles.root会被合并到根<span>上,classNames.indicator与styles.indicator会被合并到内部状态点(status-dot)或滚动数字(scroll-number)节点上(index.tsx)。此外,ConfigProvider同样支持通过badge.classNames/badge.styles为全局 Badge 统一注入语义化样式。
主题变量(Design Token)
Badge 组件支持通过 ConfigProvider 的theme.components.Badge配置组件级 Token。参考 组件 Token 演示:
<ConfigProvider theme={{ components: { Badge: { indicatorHeight: 24, indicatorHeightSM: 18, dotSize: 4, textFontWeight: 'bold', statusSize: 8, }, }, }} > {/* ... */} </ConfigProvider>组件级 Token 的完整定义与默认值见 style/index.ts 与prepareComponentToken(style/index.ts):
| Token | 说明 | 默认值计算 |
|---|---|---|
| indicatorZIndex | 徽标 z-index | auto |
| indicatorHeight | 徽标高度 | Math.round(fontSize * lineHeight) - 2 * lineWidth |
| indicatorHeightSM | 小号徽标高度 | fontSize |
| dotSize | 点状徽标尺寸 | fontSizeSM / 2 |
| textFontSize | 徽标文本尺寸 | fontSizeSM |
| textFontSizeSM | 小号徽标文本尺寸 | fontSizeSM |
| textFontWeight | 徽标文本粗细 | normal |
| statusSize | 状态徽标尺寸 | fontSizeSM / 2 |
同时 Badge 还依赖若干全局派生 Token(见prepareToken,style/index.ts),其中几个值得关注:
badgeColor:徽标默认背景色,取全局colorError(红色系),这也是数字徽标默认是红色的原因;badgeColorHover:hover 时的背景色,取colorErrorHover;badgeTextColor:徽标文字颜色,取colorBgContainer(通常为白色);badgeProcessingDuration:processing状态脉冲动画周期,固定1.2s;badgeShadowSize/badgeShadowColor:徽标外圈描边(用 box-shadow 模拟细边框),取全局lineWidth与colorBorderBg。
数字滚动动画原理
Badge 的数字切换带有一个逐位“滚动/翻牌”动画,这是它区别于普通角标的最大视觉特征。整体渲染链路为:
- 外层
InternalBadge通过CSSMotion(rc-motion)控制徽标的出现/消失缩放动画(-zoom系列,motionDeadline={1000},见 index.tsx); - 数字部分交由 ScrollNumber.tsx 渲染为
<sup>元素,内部将数字字符串按字符拆分; - 每个字符由 SingleNumber.tsx 负责逐位滚动:它先生成从旧值到新值的一段连续数字单位列表(
UnitNumber),再通过transform: translateY(...)将容器偏移到目标位置,onTransitionEnd后收敛为静态单位。
关键实现细节(SingleNumber.tsx):
- 仅对整数启用逐位滚动:
count && Number(count) % 1 === 0(ScrollNumber.tsx),浮点数(如3.5)直接整体渲染; - 滚动方向由新旧 count 大小决定:
unit = prevCount < count ? 1 : -1,并计算从旧值滚到新值的最短路径偏移getOffset; - 若浏览器不支持 transitionend 事件,则用 1000ms 定时器兜底(SingleNumber.tsx);
- 为了兼容旧用法
<Badge count={4} style={{ borderColor: '#d9d9d9' }} />,当样式里带borderColor时,ScrollNumber 会用boxShadow: 0 0 0 1px borderColor inset模拟边框(ScrollNumber.tsx),对应测试见 index.test.tsx。
此外,出现/消失与 processing 脉冲动画均在样式文件中以 Keyframes 定义(antZoomBadgeIn/Out、antNoWrapperZoomBadgeIn/Out、antStatusProcessing、antBadgeLoadingCircle,见 style/index.ts):processing状态通过::after伪元素循环scale(0.8 → 2.4)并渐隐实现呼吸扩散效果(style/index.ts)。
常用组合场景
独立使用(not-a-wrapper)
Badge 可以不包裹任何子元素独立存在(count 或 status 模式),此时自动追加ant-badge-not-a-wrapper类(index.tsx),样式上徽标不再绝对定位、而是作为行内元素参与布局(style/index.ts),并且缩放动画的原点变为自身中心。参考 独立使用演示:
<Badge count={show ? 11 : 0} showZero color="#faad14" /> <Badge count={show ? 25 : 0} />动态切换
用 state 驱动 count 变化即可实现动态徽标,配合减/加/随机按钮体验数字滚动动画。参考 动态演示,其中用Switch控制dot的显隐,演示动画的进入与离开。注意源码中徽标隐藏后仍会缓存最后一次的 count 与 dot 状态(countRef、displayCountRef、isDotRef,见 index.tsx),避免离场动画期间数字闪变。
可点击
将 Badge 包进<a>即可实现整体可点击(link.tsx):
<a href="#"> <Badge count={5}> <Avatar shape="square" size="large" /> </Badge> </a>样式文件同时定义了a:hover &下的背景变化(badgeColorHover),保证 hover 时徽标有反馈(style/index.ts)。
与 Tooltip 组合
Badge 可与 Tooltip 自由组合,例如在错误状态点上悬浮提示修复信息,相关测试见 index.test.tsx。
测试与验证
仓库为 Badge 提供了完整的测试覆盖,位于 components/badge/__tests__:
- index.test.tsx:核心行为测试,包括 mount/rtl 基础测试、float/负数展示、dot 边界、自定义 title、offset 与 ReactNode count 组合、与 Tooltip 组合、数字变化动画快照、borderColor 兼容等;
- ribbon.test.tsx:缎带行为测试;
- demo.test.tsx 与 demo-extend.test.tsx:对全部官方 demo 的渲染与快照回归;
- image.test.ts:视觉回归测试。
总结
Badge 虽是一个小组件,但信息密度很高:从 API 层面看,它同时支持数字徽标、小红点、状态点、多彩徽标与缎带五种形态;从实现层面看,它内部封装了 rc-motion 缩放动画、逐位数字滚动、RTL 适配、预设色系统与组件级 Design Token。理解 index.tsx 中count/overflowCount/showZero/dot的联动判定逻辑、SingleNumber.tsx 的滚动算法以及 style/index.ts 的 Token 体系,能帮助你在遇到定制需求时快速定位并优雅解决。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考