在 Ant Design 中用 character 属性定制 Rate 评分图标:字母、数字、图标与中文
2026/9/10 7:19:06 网站建设 项目流程

在 Ant Design 中用 character 属性定制 Rate 评分图标:字母、数字、图标与中文

【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design

Rate 组件默认以星形图标表达评分等级,但在问卷、表情评价、活动打分等场景中往往需要把“星星”替换为更有语义感的图形或文字。本文以 Ant Design 仓库中 character 官方演示 为线索,完整讲解character属性支持的全部取值形态(ReactNode、回调函数),并结合组件源码、样式 Token 与测试用例,说明自定义字符与半星、尺寸、Tooltip、键盘操作等能力如何协同工作,帮助你直接复用出可运行的评分场景。

演示要解决的问题:把默认星形换成“其他字符”

demo/character.md 的中文说明非常直白:

可以将星星替换为其他字符,比如字母,数字,字体图标甚至中文。

也就是说,Rate 的每一个评分单元并不局限于StarFilled图标,而是一个可完全自定义渲染内容的“字符槽”。把character属性从默认的星形图标换成任意内容,即可得到不同的评分外观,例如字母 A 作为评分刻度、中文“好/坏”作为评价文案、心形图标作为收藏评分等。

官方演示完整代码与逐行解读

character演示的可运行源码位于 components/rate/demo/character.tsx:

import React from 'react'; import { HeartOutlined } from '@ant-design/icons'; import { Flex, Rate } from 'antd'; const App: React.FC = () => ( <Flex vertical gap="medium"> <Rate character={<HeartOutlined />} allowHalf /> <Rate character="A" allowHalf style={{ fontSize: 36 }} /> <Rate character="好" allowHalf /> </Flex> ); export default App;

这段代码用三条 Rate 实例展示了三类最常见的自定义字符:

  1. character={<HeartOutlined />}:传入一个图标元素@ant-design/icons的心形图标)。由于图标字体天然跟随父级font-size缩放,因此可以像文字一样参与半星裁切。
  2. character="A":传入字母字符串,配合style={{ fontSize: 36 }}放大字号,得到“36px 的 A 字评分条”。
  3. character="好":传入中文字符,直接得到中文语义的评分单元。

三条 Rate 都开启了allowHalf(半选),说明自定义字符与半星模式可以无缝组合——这一点与官方文档 API 表格中的allowHalf(默认false)一致。而整个示例用Flex vertical gap="medium"纵向排布,保证三个评分条之间有合理的间距。

character 属性的完整取值类型

官方 Rate API 文档 中character的类型定义如下:

属性说明类型默认值版本
character自定义字符ReactNode \| (RateProps) => ReactNode<StarFilled />function 写法自 4.4.0 起

由此可以确定两点核心事实:

  • 默认值StarFilled(星形实心图标),这正是 index.tsx 中character = <StarFilled />解构默认值对应的内容;
  • character除了接收普通 ReactNode,还支持回调函数写法(4.4.0 起引入),这正是另一则演示 character-function.md 的主题:“可以使用(RateProps) => ReactNode的方式自定义每一个字符”

进阶:用函数按“第几个评分位”渲染不同字符

只传一个 ReactNode,会让所有评分位都长得一样;当希望“1~2 星是哭脸、3 星是面无表情、4~5 星是笑脸”这类逐位差异化时,就需要使用函数形式。仓库中配套的 components/rate/demo/character-function.tsx 给出了可直接复用的写法:

import React from 'react'; import { FrownOutlined, MehOutlined, SmileOutlined } from '@ant-design/icons'; import { Flex, Rate } from 'antd'; const customIcons: Record<number, React.ReactNode> = { 1: <FrownOutlined />, 2: <FrownOutlined />, 3: <MehOutlined />, 4: <SmileOutlined />, 5: <SmileOutlined />, }; const App: React.FC = () => ( <Flex gap="medium" vertical> <Rate defaultValue={2} character={({ index = 0 }) => index + 1} /> <Rate defaultValue={3} character={({ index = 0 }) => customIcons[index + 1]} /> </Flex> );

这段代码演示了两个实用技巧:

  • 数字评分character={({ index = 0 }) => index + 1}利用回调参数中的index(从 0 开始)渲染1、2、3、4、5,直接把 Rate 变成数字打分器;
  • 按位映射图标character={({ index = 0 }) => customIcons[index + 1]}通过index + 1作为 key 去取事先准备好的图标映射表,实现“低分哭脸、高分笑脸”的情感评分。

回调参数被解构时给了index = 0的默认值,这是为了保证在 index 未传入等边界情况下仍然安全,实际使用时建议同样保留这一默认值处理。

源码级原理:character 如何进入 RcRate 并兼容 Tooltip

从 components/rate/index.tsx 可以看到 Rate 是对@rc-component/rate(RcRate)的一层封装,character相关的处理逻辑集中在几处:

const { ... character = <StarFilled />, ... } = props; const characterRender: RcCharacterRender = (node, { index = 0 }) => { if (!tooltips) { return node; } const tooltipsItem = tooltips[index]; if (isPlainObject<TooltipProps>(tooltipsItem)) { return <Tooltip {...tooltipsItem}>{node}</Tooltip>; } return <Tooltip title={tooltipsItem}>{node}</Tooltip>; }; return ( <RcRate ref={ref} character={character} characterRender={characterRender} ... /> );

这里包含两层重要设计:

  1. props 默认值合并:未显式传入character时,默认使用<StarFilled />,因此 API 表格中“默认值<StarFilled />”是组件内部真实存在的兜底,而不是文档空谈。
  2. characterRendertooltips的组合:自定义字符在最终渲染前会经过characterRender包装——一旦通过tooltips提供了逐位提示文案(类型为TooltipProps[] | string[],见 API 文档),包装层就会根据当前位index取出对应项,并以Tooltip包裹该字符(当该项是纯对象时透传其 TooltipProps,否则视为title字符串)。也就是说:自定义字符并不会破坏逐位 Tooltip 提示能力,两者在封装层被解耦处理。

此外,RateProps声明继承了 RcRate 的完整属性集合(export interface RateProps extends RcRateProps),并额外补充tooltipssizerootClassName等,因此character的类型即来自底层的character/characterRender两个通道。

为什么自定义字符也能支持半星:样式层的裁切机制

许多自定义字符场景都会搭配allowHalf,这背后依赖的是 Rate 的样式实现。查看 components/rate/style/index.ts 中genRateStarStyle的生成逻辑:

.ant-rate-star { // 每个评分位内部实际上叠放了 first/second 两层内容 &-first, &-second { color: token.starBg; } &-first { position: absolute; width: 50%; height: 100%; overflow: hidden; // 左侧 50% 的裁切窗口 opacity: 0; } &-half &-first, &-half &-second { opacity: 1; } &-half &-first, &-full &-second { color: inherit; } }

结合样式可以推断其工作原理:每个评分单元会把同一字符渲染两遍,其中-first层被绝对定位在一个宽度 50% 的隐藏裁切窗口中;半星状态下两层同时显示,从而视觉上只点亮左半侧字符;全选时则由-full对应的右侧层呈现完整字符。因此只要自定义字符是正常渲染的文本/图标,就能被这套 50% 裁切与叠色机制接管——字符外观可替换,但“半颗星”的底层布局逻辑保持不变。这也是演示中“心形、字母、汉字 + allowHalf”均可正确半选的原因。

自定义字符的尺寸控制与组件 Token

Rate 组件的字号直接决定了字符的显示大小。在样式入口 components/rate/style/index.ts 中可以看到:

  • 根元素.ant-ratefontSize取自token.starSize,并提供了三档尺寸:starSizeSM(small)、starSizeLG(large)与默认的starSize(medium),换算关系为controlHeight * 0.625一类的基础控件高度比例;
  • size属性('small' | 'medium' | 'large',默认'medium',见 API 文档)在 index.tsx 中被映射为ant-rate-small/ant-rate-large的 CSS 类。

因此想要单独放大某个自定义字符,有两种已验证的做法:

  1. 跟随组件尺寸:直接使用size="large",整条评分条的字符都会按starSizeLG放大;
  2. 单独覆盖字号:仿照演示在 Rate 上写style={{ fontSize: 36 }},内联样式会覆盖 Token 生成的默认字号,实现任意大小的字符展示。

若要做全局主题化定制,可参考 组件 Token 演示 中的思路,通过 ConfigProvider 覆盖以下由 style/index.ts 声明的 Component Token:

Token说明
starColor星星/被选中字符颜色(默认取token.yellow6
starSize/starSizeSM/starSizeLG中/小/大档字号
starHoverScale悬浮时的缩放变换(默认scale(1.1)
starBg未选中部分的底色(默认token.colorFillContent

值得留意的是,该文件还展示了选中态、hover 放大与键盘焦点focus-visible描边样式都定义在字符的外层> div上,因此自定义字符同样会获得悬浮放大、键盘聚焦描边等无障碍反馈,而非只是“换了张皮”。

character 之外的配套属性一览

要让自定义字符的评分条完整可用,通常会与下列官方属性组合(均见 Rate API 文档,此处整理与字符评分最相关的一组):

属性说明默认值
allowHalf是否允许半选false
count评分位总数5
defaultValue非受控默认值0
value受控当前值-
disabled只读,无法交互false
keyboard支持键盘操作(5.18.0 起)true
size尺寸'medium'
tooltips逐位自定义提示TooltipProps[] \| string[]-
onChange(value: number)选择回调-
onHoverChange(value: number)鼠标悬停变化回调-
onFocus/onBlur/onKeyDown焦点与按键回调-

另外 Rate 实例还暴露blur()focus()两个方法用于手动管理焦点。结合前文characterRender的实现可见:tooltips既可以是字符串数组(快捷提示文案),也可以是逐位独立的TooltipProps对象数组(可精细控制titleplacement等),两条路径都会正确包在自定义字符外层。

测试验证:演示被完整纳入快照与扩展渲染

仓库的测试体系印证了character自定义字符是稳定的公开能力:

  • components/rate/tests/demo.test.tsx.snap 中存在renders components/rate/demo/character.tsx correctlyrenders components/rate/demo/character-function.tsx correctly两组快照,说明每个 demo 都会被真实渲染并与快照比对,防止字符替换逻辑意外回归;
  • 扩展上下文测试 demo-extend.test.ts.snap 同样覆盖这两个 demo(extend context correctly),验证其在 ConfigProvider 扩展上下文下仍可正常渲染;
  • components/rate/tests/index.test.tsx 通过focusTestmountTestrtlTest等共享测试用例(见 tests/shared)对 Rate 做了挂载、焦点与 RTL 方向的基线校验,其中也包含对size类名(ant-rate-small/ant-rate-large)的断言。

快速上手建议

在实际项目中使用自定义字符时,可遵循以下已被演示与源码共同验证的组合方式:

  1. 整体替换:单值character={<Icon />}character="字",适合全量统一外观;
  2. 逐位替换character={({ index }) => ...},适合按等级区分语义(数字 1~5、哭脸/笑脸等),记得对index做安全默认处理;
  3. 搭配半星allowHalf与自定义字符无冲突,字符会被 50% 裁切层正确渲染;
  4. 调整大小:优先用size,需要精细控制时内联fontSize或走 ConfigProvider 覆盖starSize系列 Token;
  5. 补充可访问性与提示:保持默认keyboard开启以获得方向键与焦点描边反馈,需要逐位说明时传tooltips数组,其会由characterRender自动包装到每个自定义字符上。

【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询