ant-design Badge 徽章组件全解:API 属性、语义化 DOM 样式与设计令牌
本篇技术指南基于 ant-design 仓库中的 Badge 组件文档(components/badge/index.en-US.md)及其源码实现展开,完整覆盖徽标在“未读数展示、状态指示、Ribbon 缎带”三类场景下的全部属性用法,并结合 Badge 主实现、Ribbon 实现、数字滚动组件 与 样式令牌定义,讲清每个属性的底层行为、默认值来源与可定制点,帮助读者既能直接复制可运行的示例,也能深入理解徽标的显示/隐藏判定与动画机制。
何时使用
Badge(徽章)通常出现在通知铃铛、用户头像等需要强视觉吸引力元素的附近,典型用途是展示未读消息数量。在 ant-design 中,它被归类为 Data Display(数据展示)组件,通过 count 数字、dot 红点、status 状态点三种形态承载“数量/状态”这一类轻量信息,另有 Badge.Ribbon 缎带变体用于卡片、图片等容器的角标标注。
快速上手
最基础的用法是把徽标包裹在目标元素外层,count 决定展示内容:
import { Avatar, Badge, Space } from 'antd';
const App = () => (
<Space size="medium">
<Badge count={5}>
<Avatar shape="square" size="large" />
</Badge>
{/* count 为 0 时默认隐藏,showZero 强制显示 */}
<Badge count={0} showZero>
<Avatar shape="square" size="large" />
</Badge>
{/* count 接受任意 ReactNode,可传入图标 */}
<Badge count={<ClockCircleOutlined style={{ color: '#f5222d' }} />}>
<Avatar shape="square" size="large" />
</Badge>
</Space>
);
示例来自 basic.tsx。若目标元素不需要包裹(如独立使用的角标),可以直接省略 children,此时根节点会额外加上 ${prefixCls}-not-a-wrapper 类名(见 Badge.tsx#L229),对应文档中的 Standalone 示例(no-wrapper.tsx)。
核心属性实战
未读数与溢出计数
count 的类型是 ReactNode(不限数字),overflowCount 控制最大显示值,默认 99(在 Badge.tsx#L70 中以解构默认值形式给出)。当数字超过上限时,渲染结果会替换为 ${overflowCount}+,这段逻辑直接写在组件里:
// components/badge/Badge.tsx
const numberedDisplayCount = (
(count as number) > (overflowCount as number) ? `${overflowCount}+` : count
) as string | number | null;
import { Avatar, Badge, Space } from 'antd';
const App = () => (
<Space size="large">
<Badge count={99}><Avatar shape="square" size="large" /></Badge>
<Badge count={100}><Avatar shape="square" size="large" /></Badge>
{/* 自定义上限:显示 10+ */}
<Badge count={99} overflowCount={10}><Avatar shape="square" size="large" /></Badge>
{/* 显示 999+ */}
<Badge count={1000} overflowCount={999}><Avatar shape="square" size="large" /></Badge>
</Space>
);
以上即 overflow.tsx 示例。
showZero 默认为 false:当 count 为 0(或 text 为 0)时徽标整体隐藏;传入 showZero 后零值也会展示。隐藏与否的完整判定见 Badge.tsx#L111-L124,其中 isZero、ignoreCount、isStatusBadge 三个布尔值共同决定了后续走“数字/红点”还是“状态点”渲染分支。
红点模式(dot)与动态更新
dot 为 true 时用红点替代数字,默认 false。源码中 showAsDot = dot && !isZero(Badge.tsx#L161),即数字为零时即使声明 dot 也不渲染。动态场景(计数器增减、红点开关)由 change.tsx 演示:
import { useState } from 'react';
import { Avatar, Badge, Button, Space, Switch } from 'antd';
const App = () => {
const [count, setCount] = useState(5);
const [show, setShow] = useState(true);
return (
<Space vertical>
<Space size="large">
<Badge count={count}><Avatar shape="square" size="large" /></Badge>
{/* 用 +/- 按钮与随机按钮驱动 count 变化 */}
</Space>
<Space size="large">
<Badge dot={show}><Avatar shape="square" size="large" /></Badge>
<Switch checked={show} onChange={setShow} aria-label="Show badge dot" />
</Space>
</Space>
);
};
偏移与尺寸
offset: [number, number]:第一个值是水平偏移,第二个是垂直偏移。从 Badge.tsx#L127-L138 可以看到,第一个值经parseInt后以负值写入insetInlineEnd(即徽标向右挪出容器的像素数),第二个值写入marginTop。用法如 offset.tsx:<Badge count={5} offset={[10, 10]}>。size:取值为medium|small,仅在设置了count时生效,控制数字圆角框的大小(渲染${prefixCls}-count-sm类,见 Badge.tsx#L280)。源码默认值是'medium';文档 API 表中未写默认值,但注意size="default"已在开发模式下标记为废弃并会触发告警,建议直接使用medium(废弃告警逻辑见 Badge.tsx#L96-L99)。
状态点(status)与文字
status 取值 success | processing | default | error | warning,用于把徽标变成“状态点 + 说明文字”的组合;text 即状态点右侧的展示文本。完整五种状态的用法见 status.tsx:
import { Badge, Space } from 'antd';
const App = () => (
<>
<Space>
<Badge status="success" />
<Badge status="error" />
<Badge status="default" />
<Badge status="processing" />
<Badge status="warning" />
</Space>
<Space vertical>
<Badge status="success" text="Success" />
<Badge status="error" text="Error" />
{/* ... 其余状态同理 */}
</Space>
</>
);
渲染分支上,当“没有 children 且存在 status/color、且数字被隐藏”时,组件会走独立的状态徽标分支(isStatusBadge,Badge.tsx#L240-L258),只输出一个状态点与可选的 ${prefixCls}-status-text 文本节点。processing 状态点的呼吸扩散动效由 style/index.ts#L115-L118 中的 antStatusProcessing 关键帧定义。
自定义颜色与悬停标题
color:同时适用于状态点与数字徽标。若传入的是 ant-design 预置色(如pink、cyan、volcano,colorful.tsx 演示了八种预置色),组件会生成${prefixCls}-color-${color}语义类名;若传入任意 CSS 颜色值,则通过内联样式直接设置color/background(Badge.tsx#L220-L223)。title(6.5.0 起):鼠标悬停在数字徽标上的原生 tooltip 文本;不传时若count本身是字符串或数字则自动作为 title 兜底(Badge.tsx#L192-L194),传null或false可显式移除,对应调试示例 title.tsx。- 可点击场景:把
Badge直接包在<a>外层即可(link.tsx),点击区域覆盖整个徽标。
Badge.Ribbon 缎带
Badge.Ribbon 用于在卡片、图片等块级容器上挂一条“缎带”角标。在 index.tsx 中它被静态挂载到主组件上:
import { Badge, Card } from 'antd';
<Badge.Ribbon text="Hippies" color="pink">
<Card size="small" title="Pushes open the window">and raises the spyglass.</Card>
</Badge.Ribbon>
完整的多色示例见 ribbon.tsx。API 如下:
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| color | 自定义 Ribbon 颜色(预置色或任意 CSS 颜色) | string |
- | - |
| placement | 缎带位置,start / end 跟随文本方向(RTL/LTR) |
'start' | 'end' |
'end' |
- |
| text | 缎带内的内容 | ReactNode |
- | - |
| classNames / styles | 语义化 DOM 定制,支持对象或函数 | Record<SemanticDOM, ...> |
- | 6.0.0 |
从 Ribbon.tsx 源码看:placement 会映射为 ${prefixCls}-placement-${placement} 类名;非预置色会同时写入缎带背景色与“角”(corner)的文本色(Ribbon.tsx#L106-L111),从而让折叠角的阴影颜色与缎带保持一致;组件还通过 useImperativeHandle 暴露 nativeElement 引用(RibbonRef,Ribbon.tsx#L42-L44)。调试示例 ribbon-debug.tsx 进一步演示了 placement="start" 与自定义颜色的组合。
语义化 DOM:classNames 与 styles
自 5.7.0(Badge)/ 6.0.0(Ribbon)起,两个组件都支持 classNames 与 styles 两个属性,按“语义结构”粒度定制内部节点的类名与内联样式,且都支持对象或函数两种写法(函数入参为 info: { props },可按当前 props 动态返回)。
Badge 的语义结构(见 demo/_semantic.tsx):
| 结构 | 含义 |
|---|---|
root |
根元素:相对定位、行内块布局、适应内容宽度等基础布局样式 |
indicator |
指示器元素:定位、层级、尺寸、颜色、字体、背景、圆角、阴影、过渡动画等完整徽标样式 |
Ribbon 的语义结构(见 demo/_semantic_ribbon.tsx):root(外层包裹容器)、content(缎带文字)、indicator(缎带主体)。
官方示例 style-class.tsx(标注 6.0.0 起可用)展示了对象式与函数式的完整组合:
import type { BadgeProps, GetProp } from 'antd';
import type { RibbonProps } from 'antd/es/badge/Ribbon';
// 对象式:直接声明
const badgeStyles: BadgeProps['styles'] = {
root: { borderRadius: 8 },
};
// 函数式:根据当前 props 动态返回
const badgeStylesFn: BadgeProps['styles'] = (info) => {
if (info.props.size === 'medium') {
return { indicator: { fontSize: 14, backgroundColor: '#696FC7' } };
}
return {};
};
const ribbonStylesFn: RibbonProps['styles'] = (info) => {
if (info.props.color === '#696FC7') {
return { content: { fontWeight: 'bold' } };
}
return {};
};
底层实现上,两个组件都通过 useMergeSemantic 钩子(Badge.tsx#L149-L159、Ribbon.tsx#L81-L91)按“ConfigProvider 全局配置 → 组件 props”的优先级合并 classNames/styles,因此语义化定制可以与 ConfigProvider 组件级配置 同时生效且互不冲突。
设计令牌(Design Token)
文档 API 末尾的 Design Token 表格由 ComponentTokenTable 生成,其数据源即 style/index.ts 中导出的令牌接口。从源码结构看,Badge 的令牌分为两层:
组件专用令牌(ComponentToken):
| 令牌 | 说明 |
|---|---|
indicatorZIndex |
徽标 z-index |
indicatorHeight |
徽标高度 |
indicatorHeightSM |
小号徽标高度 |
dotSize |
点状徽标尺寸 |
textFontSize / textFontSizeSM |
徽标文本字号 / 小号徽标文本字号 |
textFontWeight |
徽标文本字重 |
statusSize |
状态徽标尺寸 |
paddingInline |
多字符徽标(如 “99+”)的水平内边距 |
别名令牌(BadgeToken,由全局 seed 推导):badgeFontHeight、badgeTextColor、badgeColor、badgeColorHover、badgeShadowSize、badgeShadowColor、badgeProcessingDuration(processing 状态动效时长)、badgeRibbonOffset(缎带偏移量)、badgeRibbonCornerTransform / badgeRibbonCornerFilter(缎带折叠角的变换与滤镜)。这些令牌均可在 ConfigProvider 的 theme.components.Badge 中覆盖;仓库中的调试示例 component-token.tsx 展示了组件令牌的实际配置形态。
源码级实现要点
1. 显示/隐藏与“活值”缓存。 数字徽标用 CSSMotion(motionName="${prefixCls}-zoom",motionAppear={false},motionDeadline={1000},Badge.tsx#L263-L268)包裹,实现出现/消失的缩放动画。值得注意的细节是:count、显示内容和 dot 状态分别保存在三个 useRef 中,且仅在未隐藏时更新(Badge.tsx#L170-L188)——源码注释解释得很直白:“remove motion should not change count display”,即徽标在退场动画期间仍显示旧值,避免动画中途数字突变或红点抖动。
2. 数字滚动动画。 展示层由 ScrollNumber.tsx 承担,默认渲染为 <sup> 上标元素。它只对整数做逐位滚动动画(Number(count) % 1 === 0 判断),把数字拆成字符数组,每位交给 SingleNumber.tsx 用 CSS transition 完成“进位”位移;并内置了 setTimeout(..., 1000) 的兜底逻辑,在浏览器不支持 transitionend 事件时也能正确落定。此外,ScrollNumber 会把外层传入的 borderColor 转换为 box-shadow: 0 0 0 1px <color> inset(ScrollNumber.tsx#L73-L78),以兼容“用 style 设置边框”的老用法。
3. 可访问性与 RTL。 多字符数字会额外加 ${prefixCls}-multiple-words 类(Badge.tsx#L281-L282),ScrollNumber 内部用 <bdi> 隔离双向文本;方向由 useComponentConfig('badge') 提供的 direction 驱动,RTL 语言下根节点自动加 ${prefixCls}-rtl 类,offset 使用 insetInlineEnd 而非 right 以正确适配文本方向。
4. 全局可配置项。 文档 API 表中 “Global Config” 一列标记为 ×,意味着 count、color、offset 等实例属性暂不支持通过 ConfigProvider 全局配置;但 classNames/styles 语义化配置与 theme.components.Badge 设计令牌属于全局可配置路径(Badge 与 Ribbon 分别读取 useComponentConfig('badge') / useComponentConfig('ribbon'),见 Badge.tsx#L83-L92)。
Badge API 速查
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| color | 自定义徽标颜色 | string |
- | - |
| count | 展示的数字/内容 | ReactNode |
- | - |
| classNames | 语义化 DOM 类名定制(对象或函数) | Record<SemanticDOM, string> | (info) => ... |
- | 5.7.0 |
| dot | 以红点替代 count |
boolean |
false |
- |
| offset | 徽标点偏移 | [number, number] |
- | - |
| overflowCount | 最大显示数 | number |
99 |
- |
| showZero | count 为 0 时是否展示 |
boolean |
false |
- |
| size | 设置了 count 时控制徽标大小 |
medium | small |
- | - |
| status | 设置为状态点 | success | processing | default | error | warning |
- | - |
| styles | 语义化 DOM 内联样式定制(对象或函数) | Record<SemanticDOM, CSSProperties> | (info) => ... |
- | 5.7.0 |
| text | status 模式下状态点的展示文本 |
ReactNode |
- | - |
| title | 悬停提示文本,null/false 可移除 |
string | null | false |
- | 6.5.0 |
通用属性参见 ant-design 文档的 Common props 约定。
参考文件
- 组件文档:components/badge/index.en-US.md
- 主实现:components/badge/Badge.tsx、components/badge/Ribbon.tsx
- 动画与展示:components/badge/ScrollNumber.tsx、components/badge/SingleNumber.tsx
- 样式与令牌:components/badge/style/index.ts
- 导出入口:components/badge/index.tsx
- 示例目录:components/badge/demo(basic / overflow / dot / change / offset / size / status / colorful / ribbon / style-class 等)
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00