首页
/ ant-design Badge 徽章组件全解:API 属性、语义化 DOM 样式与设计令牌

ant-design Badge 徽章组件全解:API 属性、语义化 DOM 样式与设计令牌

2026-09-06 14:34:29作者:滕妙奇

本篇技术指南基于 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:当 count0(或 text0)时徽标整体隐藏;传入 showZero 后零值也会展示。隐藏与否的完整判定见 Badge.tsx#L111-L124,其中 isZeroignoreCountisStatusBadge 三个布尔值共同决定了后续走“数字/红点”还是“状态点”渲染分支。

红点模式(dot)与动态更新

dottrue 时用红点替代数字,默认 false。源码中 showAsDot = dot && !isZeroBadge.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、且数字被隐藏”时,组件会走独立的状态徽标分支(isStatusBadgeBadge.tsx#L240-L258),只输出一个状态点与可选的 ${prefixCls}-status-text 文本节点。processing 状态点的呼吸扩散动效由 style/index.ts#L115-L118 中的 antStatusProcessing 关键帧定义。

自定义颜色与悬停标题

  • color:同时适用于状态点与数字徽标。若传入的是 ant-design 预置色(如 pinkcyanvolcanocolorful.tsx 演示了八种预置色),组件会生成 ${prefixCls}-color-${color} 语义类名;若传入任意 CSS 颜色值,则通过内联样式直接设置 color/backgroundBadge.tsx#L220-L223)。
  • title(6.5.0 起):鼠标悬停在数字徽标上的原生 tooltip 文本;不传时若 count 本身是字符串或数字则自动作为 title 兜底(Badge.tsx#L192-L194),传 nullfalse 可显式移除,对应调试示例 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 引用(RibbonRefRibbon.tsx#L42-L44)。调试示例 ribbon-debug.tsx 进一步演示了 placement="start" 与自定义颜色的组合。

语义化 DOM:classNames 与 styles

自 5.7.0(Badge)/ 6.0.0(Ribbon)起,两个组件都支持 classNamesstyles 两个属性,按“语义结构”粒度定制内部节点的类名与内联样式,且都支持对象或函数两种写法(函数入参为 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-L159Ribbon.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 推导)badgeFontHeightbadgeTextColorbadgeColorbadgeColorHoverbadgeShadowSizebadgeShadowColorbadgeProcessingDuration(processing 状态动效时长)、badgeRibbonOffset(缎带偏移量)、badgeRibbonCornerTransform / badgeRibbonCornerFilter(缎带折叠角的变换与滤镜)。这些令牌均可在 ConfigProvidertheme.components.Badge 中覆盖;仓库中的调试示例 component-token.tsx 展示了组件令牌的实际配置形态。

源码级实现要点

1. 显示/隐藏与“活值”缓存。 数字徽标用 CSSMotionmotionName="${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> insetScrollNumber.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” 一列标记为 ×,意味着 countcoloroffset 等实例属性暂不支持通过 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 约定。

参考文件

登录后查看全文
热门项目推荐
相关项目推荐