Ant Design Slider `tooltip.formatter` 完全指南:自定义提示内容与隐藏 Tooltip 的底层原理
2026/9/10 14:05:02 网站建设 项目流程

Ant Design Slidertooltip.formatter完全指南:自定义提示内容与隐藏 Tooltip 的底层原理

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

导读

本文围绕 antd Slider(滑条)组件中tooltip.formatter这一 API 展开:它允许开发者在用户拖拽手柄(handle)时,按需格式化 Tooltip 中展示的值(如追加%、货币符号或转为自定义 ReactNode),并支持通过返回null或直接传null来彻底隐藏 Tooltip。读完本文,你将掌握formatter的类型签名、undefined/null/函数三种传参下的差异、它在 antd 源码中的实现与默认行为,以及若干可直接落地的实战写法。

一、示例原型:一次看懂 formatter 的两种核心用法

该主题对应仓库中 tip-formatter demo 说明,其配套源码为 tip-formatter.tsx,核心代码如下:

import React from 'react'; import type { SliderSingleProps } from 'antd'; import { Slider } from 'antd'; const formatter: NonNullable<SliderSingleProps['tooltip']>['formatter'] = (value) => `${value}%`; const App: React.FC = () => ( <> <Slider tooltip={{ formatter }} /> <Slider tooltip={{ formatter: null }} /> </> ); export default App;

这段代码在同一页面渲染了两个滑块,覆盖了formatter的两种典型语义:

  1. 传入格式化函数formatter: (value) => \${value}%`—— 滑条将当前值交给formatter,函数返回值即为 Tooltip 中展示的内容。例如拖到 50 时 Tooltip 显示50%`。
  2. 传入nulltooltip.formatter = null—— 该滑条上的 Tooltip 将完全不出现,即使拖动或悬停也不展示。

demo 中给出的formatter变量声明方式值得学习:直接复用SliderSingleProps['tooltip']formatter类型并通过NonNullable去除可空性,保证回调参数value具备完整的类型推导,避免手写类型与官方签名不一致。

二、tooltip.formatter的 API 定义与参数语义

在 Slider 组件 API 文档 中,formatter的官方定义如下:

属性说明类型默认值版本
formatterSlider 会将当前值传给formatter,在 Tooltip 中展示其返回值;当返回值(函数内部返回)为null时隐藏 Tooltipvalue => ReactNode \| nullIDENTITY(恒等函数)4.23.0

需要精确区分文档中提到的两种“隐藏”写法:

  • tooltip.formatter = null(配置层为null:表示“禁用 formatter 且不展示 Tooltip”,作用于整个滑块;
  • formatter函数内部返回null(如(value) => value > 80 ? null : \${value}%``):表示“按当前值动态决定是否隐藏 Tooltip”,可用于在值越过阈值后让提示自动消失。

当返回类型为ReactNode时,你甚至可以返回图标、<span>元素或任意 React 节点,而不局限于纯文本。

tooltip.open的关系

同属于tooltip子属性的还有 show-tooltip demo 讲解的openopen: true时 Tooltip 始终显示(拖拽、悬停皆显示);open: false时始终隐藏。两者侧重点不同:

  • open控制的是 Tooltip显隐开关,不关心内容;
  • formatter控制的是 Tooltip 的内容渲染,但其返回值又具备“反向干预显隐”的能力(返回null即隐藏)。

若你希望 Tooltip 一直可见、但内容按需变化,可组合使用tooltip={{ open: true, formatter }}

三、源码级解析:默认行为与null隐藏的实现原理

默认 formatter 并非简单透传

若完全不传tooltip.formatter,按文档默认值 IDENTITY 的字面理解是把值原样显示。查看 Slider 组件实现 可看到真实的兜底逻辑:

function getTipFormatter(tipFormatter?: Formatter) { if (tipFormatter || tipFormatter === null) { return tipFormatter; } return (val?: number) => (isNumber(val) ? val.toString() : ''); }

即源码内部做了三层分支处理:

  1. formatter函数:直接采用,返回值决定 Tooltip 内容;
  2. formatternull:同样原样保留(tipFormatter === null被显式判断),作为“隐藏标记”下发给底层渲染,最终阻止 Tooltip 出现;
  3. formatterundefined(未传):使用内置默认函数,把数值toString()后展示,undefined值则渲染为空字符串。

关键点在于:undefinednull在 JS 中都被视为“空”,但这里通过tipFormatter || tipFormatter === null的显式分支区分了二者 ——只有null才代表“隐藏 Tooltip”,而undefined会被默认函数接管

Tooltip 的显隐与对齐状态机

在 index.tsx 中,Tooltip 显隐由三组状态合并得出:

const [hoverOpen, setHoverOpen] = useDelayState(false); const [focusOpen, setFocusOpen] = useDelayState(false); ... const lockOpen = tooltipOpen; const activeOpen = (hoverOpen || focusOpen) && lockOpen !== false;
  • hoverOpen:鼠标悬停手柄时置真;
  • focusOpen:键盘聚焦手柄时置真(滑块默认支持keyboard操作,方向键移动同样会唤起提示);
  • lockOpen:来源于tooltip.open,起到“开关锁”作用。

Tooltip 实际渲染时,每次拖拽或聚焦都会把当前值通过formatter转换为title内容传给 SliderTooltip,由其mergedOpen = open && !draggingDelete进一步决定最终显隐。

对 Tooltip 基础组件的复用

从实现看,滑条提示并非自绘,而是复用了 antd 的通用 Tooltip 组件):SliderTooltipTooltip的一层薄封装,额外增加了两个职责——在拖拽删除手柄(draggingDelete)时强制关闭,以及在每次内容变化后通过raf+forceAlign()重新校正气泡位置(见 SliderTooltip.tsx),避免提示内容变宽后错位。因此你给 Slider 的tooltip.placementtooltip.getPopupContainer等属性,语义均与基础 Tooltip 对齐。

四、测试验证:官方如何保证formatter: null的行为

仓库通过自动化测试锁定了该 API 的语义。在 tooltip.test.tsx 中有一条针对性用例:

it('tooltip should not display when formatter is null or open is false', async () => { // ... <Slider defaultValue={30} tooltip={{ formatter: null }} /> // ... });

测试名称直接印证了本文第一节的说法:formatternullopenfalse效果等价——Tooltip 一律不显示,无论用户是否悬停或拖拽。同时,源码处的demo.test.ts__tests__/__snapshots__/demo.test.ts.snap亦会对 tip-formatter.tsx 渲染出的快照进行比对,确保50%这类格式化输出与 DOM 结构保持稳定,你在改动业务逻辑时可据此回归。

五、实战场景与最佳实践

1. 数值单位 / 百分比

<Slider min={0} max={100} tooltip={{ formatter: (value) => `${value}%` }} />

2. 货币与精度控制

const priceFormatter = (value?: number) => `¥ ${(value ?? 0).toFixed(2)}`; <Slider min={0} max={1000} step={10} tooltip={{ formatter: priceFormatter }} />

3. 返回 ReactNode,实现图文混排

import { SmileOutlined } from '@ant-design/icons'; <Slider tooltip={{ formatter: (value) => ( <span> <SmileOutlined /> {value}% </span> ), }} />

4. 按值动态隐藏

<Slider defaultValue={30} tooltip={{ formatter: (value) => (value !== undefined && value > 80 ? null : `${value}%`), }} />

此时值 ≤ 80 显示xx%,一旦滑过 80,Tooltip 便自动消失——这正是“返回值为null时隐藏 Tooltip”的典型用法。

5. 始终展示并自定义内容(组合open

<Slider tooltip={{ open: true, formatter: (value) => `当前刻度:${value}`, }} />

注意事项

  • formatter回调可能收到undefined(由上文默认函数对非数值的处理可知,取值存在未命中数值节点的场景),业务代码里建议先做空值兜底,如(value) => (value == null ? '' : ...)
  • 隐藏语义请统一使用null,不要用undefined表达“不想显示”——undefined会被源码视为“未配置”而落入默认文本显示分支;
  • 若同时设置了tooltip.open: false,无论formatter如何配置,Tooltip 都会被强制隐藏,两者优先级以open的开关逻辑为准(见上文activeOpen计算);
  • tooltip.formatter自 4.23.0 版本引入,旧版本中对应的过渡写法是顶层tipFormatter,antd 在 index.tsx 的 deprecated 分支 中保留了兼容映射与弃用告警,建议新代码统一走tooltip.formatter

六、小结

tooltip.formatter是 antd Slider 中“轻量但高频”的内容定制入口:传函数即可随心格式化提示文本或 React 节点,传null即可整条禁用 Tooltip。配合源码中getTipFormatterundefined/null分支设计、activeOpen状态机以及SliderTooltip的对齐刷新机制,你既能快速写出符合业务语义的滑条,也能在出现“Tooltip 为什么没显示/为什么一直显示”之类的疑问时,准确回溯到底层判定逻辑。

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

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

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

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

立即咨询