Ant Design Notification 组件全解析:全局消息通知的 API 用法、语义化定制与避坑指南
Ant Design(antd)的 Notification 是一个将全局提示消息渲染在视口四角的消息通知组件,适合承载内容较复杂、由用户交互或应用主动推送的反馈信息。本文以 components/notification/index.en-US.md 官方文档为主体,结合本仓库 components/notification/ 下的源码与演示代码,系统讲解 notification 静态方法、useNotification Hooks 两种调用方式,逐项拆解 ArgsProps 全量配置参数、notification.config() 全局默认值、语义化 DOM 定制、Design Token,以及使用 Context、前缀 prefixCls、通知宽度等高频 FAQ。读完本文,你将能按官方最佳实践接入、定制并排查 Notification 的绝大多数问题。
何时使用 Notification
Notification 用于在视口四个角中的任意一角弹出通知消息。官方文档归纳了三类典型场景:
- 包含复杂内容的通知(例如带操作按钮、长描述的消息卡片);
- 基于用户交互给出反馈,或展示用户接下来可能需要执行的步骤细节;
- 由应用主动推送的通知(如新版本发布、后台任务完成提醒)。
它适用于"有复杂内容、需要临时悬浮展示、但不需要用户强制处理"的消息场景。如果你需要强阻断式的用户确认,应使用 Modal 确认框 或 Popconfirm;如果只是页面内轻量提示,可以考虑 message。
两种调用方式:静态方法(已弃用)与 Hooks API(推荐)
本仓库的 components/notification/demo/basic.tsx 被标注为 "Static Method (deprecated)",它展示了 antd v5 时代最原始的调用方式:
import { Button, notification } from 'antd';
const openNotification = () => {
notification.open({
title: 'Notification Title',
description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
onClick: () => {
console.log('Notification Clicked!');
},
});
};
const App: React.FC = () => (
<Button type="primary" onClick={openNotification}>
Open the notification box
</Button>
);
而官方文档推荐的用法是 Hooks 方式(见 components/notification/demo/hooks.tsx)。它最大的价值在于:通知实例能够读取到它所在位置的 React Context(如 ConfigProvider 的 locale / prefixCls / theme,或业务自定义 Context)。
import React, { useMemo } from 'react';
import { Button, Divider, notification, Space } from 'antd';
import type { NotificationArgsProps } from 'antd';
type NotificationPlacement = NotificationArgsProps['placement'];
const Context = React.createContext({ name: 'Default' });
const App: React.FC = () => {
const [api, contextHolder] = notification.useNotification();
const openNotification = (placement: NotificationPlacement) => {
api.info({
title: `Notification ${placement}`,
description: <Context.Consumer>{({ name }) => `Hello, ${name}!`}</Context.Consumer>,
placement,
});
};
return (
<Context.Provider value={contextValue}>
{contextHolder}
{/* 点击按钮弹出四个角的通知 */}
</Context.Provider>
);
};
从源码结构看,useNotification 最终在 components/notification/useNotification.tsx 中调用 @rc-component/notification 的 useRcNotification,通过 Holder 渲染出列表容器,并把 success / error / info / warning / open / destroy 六个方法封装返回(keys.forEach 逐一生成带 type 的方法),因此 Hooks 实例拥有与静态方法完全一致的 API 签名。
提示:
basic.tsx演示用的是notification.open,其中传入的title是 6.0.0 起的新字段名;更早期的代码里使用message,二者在该仓库 interface.ts 中为并存关系(title ?? message取优先级),开发期message会触发 deprecated 警告(btn之于actions同理)。源码见 useNotification.tsx。
API 方法一览
官方公开的顶层方法如下:
notification.success(config)notification.error(config)notification.info(config)notification.warning(config)notification.open(config)notification.destroy(key?: String)
其中 success / error / info / warning 与 open 在 index.tsx 中通过 methods.forEach((type) => staticMethods[type] = (config) => open({ ...config, type })) 批量注册,本质上都是往 open 里注入一个 type 字段,type 再映射为对应图标与语义色。destroy() 不带参数时清空全部通知,带 key 时只销毁指定 key 的通知。
ArgsProps:单条通知的完整配置参数
以下是官方文档给出的 config 完整参数表(其中 key、duration、placement、icon、actions 等是该文档的核心内容,务必完整掌握):
| Property | Description | Type | Default | Version | Global Config |
|---|---|---|---|---|---|
| actions | 自定义操作按钮组 | ReactNode | - | 5.24.0 | × |
自定义关闭按钮组,已被 actions 取代 |
ReactNode | - | - | × | |
| className | 自定义 CSS 类 | string | - | - | 5.7.0 |
| classNames | 为组件内部每个语义结构自定义 class,支持对象或函数 | Record<SemanticDOM> , string> | (info: { props })=> Record<SemanticDOM, string> | - | 6.0.0 | 6.0.0 |
| closable | 是否展示关闭按钮 | boolean | ClosableType | true | - | × |
| closeIcon | 自定义关闭图标 | ReactNode | true | 5.7.0 起:设为 null 或 false 时隐藏关闭按钮 |
5.14.0 |
| description | 通知框内容(必填) | ReactNode | - | - | × |
| duration | 关闭前展示秒数。设为 0 或 false 永不自动关闭 |
number | false | 4.5 | - | × |
| showProgress | 是否展示自动关闭进度条 | boolean | - | 5.18.0 | × |
| pauseOnHover | 鼠标悬停时是否暂停计时 | boolean | true | 5.18.0 | × |
| icon | 自定义图标 | ReactNode | - | - | × |
| key | 通知的唯一标识 | string | - | - | × |
| title | 通知标题(6.0.0 起) | ReactNode | - | 6.0.0 | × |
通知标题(已弃用,改用 title) |
ReactNode | - | - | × | |
| placement | 出现位置:top | topLeft | topRight | bottom | bottomLeft | bottomRight |
string | topRight |
- | × |
| role | 读屏器识别的通知语义,默认 alert 会中断当前朗读并优先播报 |
alert | status |
alert |
5.6.0 | × |
| style | 自定义内联样式 | CSSProperties | - | - | 5.7.0 |
| styles | 为组件内部每个语义结构自定义内联样式,支持对象或函数 | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | 6.0.0 | 6.0.0 |
| onClick | 点击通知时触发的回调 | function | - | - | × |
| onClose | 通知关闭时触发 | function | - | - | × |
| props | 透传到通知 div 上的 data-*、aria-*、role 等属性。注意 TypeScript 下目前只放行 data-testid 而非常规 data-*,详见 TypeScript issue #28960 |
Object | - | - | × |
表中最后一列 "Global Config" 表示该字段同时可以通过 ConfigProvider 的组件级配置(components/notification 相关章节)进行全局统一设置。
ClosableType:关闭行为配置
当 closable 需要更精细控制时,可传入对象形式的 ClosableType:
| Property | Description | Type | Default |
|---|---|---|---|
| closeIcon | 自定义关闭图标 | ReactNode | undefined |
| onClose | 通知关闭时触发 | Function | - |
useNotification 的全局配置参数
notification.useNotification(config) 的 config 支持以下字段(注意:notification.config() 全局静态配置的参数与其高度重合,但不支持 stack、duration、closable,两者请勿混淆):
| Property | Description | Type | Default | Version | Global Config |
|---|---|---|---|---|---|
| bottom | placement 为 bottom / bottomRight / bottomLeft 时距视口底部的距离(px) |
number | 24 | × | |
| closeIcon | 自定义关闭图标 | ReactNode | true | 5.7.0:设为 null 或 false 时隐藏关闭按钮 |
5.14.0 |
| getContainer | 返回通知的挂载节点 | () => HTMLNode | () => document.body | × | |
| placement | 出现位置 | string | topRight |
× | |
| showProgress | 展示自动关闭进度条 | boolean | - | 5.18.0 | × |
| pauseOnHover | 悬停时暂停计时 | boolean | true | 5.18.0 | × |
| rtl | 是否启用 RTL 模式 | boolean | false | × | |
| stack | 超过阈值后通知堆叠展示 | boolean | { threshold: number } |
{ threshold: 3 } |
5.10.0 | × |
| top | placement 为 top / topRight / topLeft 时距视口顶部的距离(px) |
number | 24 | × | |
| maxCount | 最大同时展示数量,超限后丢弃最旧的 | number | - | 4.17.0 | × |
其中 maxCount 用于防止通知泛滥,stack 用于多个通知同时存在时的"堆叠卡片"效果。
全局默认配置:notification.config()
notification 还提供一个全局 config() 方法用来设置默认选项。一旦调用,之后所有通知框在展示时都会套用这些全局默认值。官方给出的示例为:
notification.config({
placement: 'bottomRight',
bottom: 50,
duration: 3,
rtl: true,
});
完整的 notification.config(options) 参数表如下:
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
| bottom | 底部定位时的视口底部距离(px) | number | 24 | |
| closeIcon | 自定义关闭图标 | ReactNode | true | 5.7.0:设为 null 或 false 时隐藏关闭按钮 |
| duration | 关闭前展示秒数。设为 0 或 null 时永不自动关闭 |
number | 4.5 | |
| getContainer | 返回通知挂载节点 | () => HTMLNode | () => document.body | |
| placement | 出现位置 | string | topRight |
|
| showProgress | 展示自动关闭进度条 | boolean | - | 5.18.0 |
| pauseOnHover | 悬停时暂停计时 | boolean | true | 5.18.0 |
| rtl | 是否启用 RTL 模式 | boolean | false | |
| top | 顶部定位时的视口顶部距离(px) | number | 24 | |
| maxCount | 最大同时展示数量,超限丢弃最旧 | number | - | 4.17.0 |
从 index.tsx 源码可以确认实现细节:notification.config(...) 实际调用 setNotificationGlobalConfig,它会把传入的配置 merge 进模块级的 defaultGlobalConfig 对象,然后通过 notification?.sync?.() 触发全局挂载点的重新同步;随后每次 open 时,flushNotificationQueue 都会以 { ...defaultGlobalConfig, ...task.config } 的方式合并——单条通知的字段优先于全局配置。
注意(4.3.0+):当通过
ConfigProvider做全局配置时,系统会默认自动开启 RTL 模式。如果单独使用静态方法,则需要像上面的示例那样显式传入rtl: true才能启用 RTL。
演示代码速览:从入门到进阶
官方文档的 Examples 区块收录了 15 个可直接运行的演示(对应 components/notification/demo/ 目录),覆盖了本组件绝大多数能力。下表帮你快速定位每个能力对应的入口文件与核心知识点:
| 演示主题 | 文件 | 讲解要点 |
|---|---|---|
| Hooks 用法(推荐) | demo/hooks.tsx | useNotification + contextHolder,配合 Context.Provider 弹四个角的通知 |
| 关闭时长 | demo/duration.tsx | duration: 0 实现永不自动关闭 |
| 带图标 | demo/with-icon.tsx | 通过 type 使用内置状态图标(success/info/warning/error) |
| 自定义操作按钮 | demo/with-btn.tsx | actions/btn 内放置按钮,调用 api.destroy() 与 api.destroy(key);配合 onClose |
| 自定义图标 | demo/custom-icon.tsx | 传入任意 icon ReactNode(如 <SmileOutlined />)覆盖默认图标 |
| 位置 placement | demo/placement.tsx | 六种 placement 对应四个角的按钮切换 |
| 更新内容 | demo/update.tsx | 用相同 key 再次 open 即可原地刷新标题与描述 |
| 堆叠展示 | demo/stack.tsx | useNotification({ stack: { threshold } }) 或 stack: false 关闭堆叠 |
| 进度条 | demo/show-with-progress.tsx | showProgress: true 展示自动关闭进度条,pauseOnHover 控制悬停是否暂停 |
| 静态方法(已弃用) | demo/basic.tsx | 早期 notification.open 用法,含 onClick 点击回调 |
| 进度条颜色 | demo/progress-color.tsx | 通过组件 Token progressBg 自定义进度条渐变 |
| 组件 Token | demo/component-token.tsx | 通过 colorSuccessBg 等 Token 定制各状态背景色 |
| 内部 Panel(勿用于生产) | demo/render-panel.tsx | _InternalPanelDoNotUseOrYouWillBeFired 仅供站点预览 |
| 语义化样式 | demo/style-class.tsx | styles 支持对象或函数,按 type 返回不同配色 |
| 语义化 DOM 预览 | demo/_semantic.tsx | 展示 classNames/styles 可用的全部语义节点 |
例如 update.tsx 展示了最常见的"更新已有通知"模式:先以固定 key: 'updatable' 打开一条通知,1 秒后用同一 key 再调一次 open,由于 key 相同,组件会原地更新而非新增一条:
api.open({
key, // key = 'updatable'
title: 'Notification Title',
description: 'description.',
});
setTimeout(() => {
api.open({
key,
title: 'New Title',
description: 'New description.',
});
}, 1000);
语义化 DOM(Semantic DOM)
从 antd 6.0.0 起,Notification 开放了语义化 DOM 定制能力:通过 classNames / styles 精确命中组件内部的语义节点(二者既支持普通对象,也支持 ({ props }) => ... 函数形式,函数可以根据单条通知的 props(如 type)动态返回不同的样式)。interface.ts 中定义的语义节点集合如下:
list:通知列表根元素——定位、z-index、宽度、滚动区域与位置样式listContent:通知列表内容元素——通知项排列、间距与高度过渡动画样式root:单条通知根元素——背景色、圆角、阴影、内边距与动画样式wrapper:图标与内容的包裹元素(6.4.0)icon:图标元素(状态色等)section:包含标题与描述的内容区域(6.4.0)title:标题元素description:描述元素actions:操作按钮组元素close:关闭按钮元素(6.4.0)progress:自动关闭进度条元素(6.4.0)
style-class.tsx 给出了对象与函数两种写法的完整示范:先定义一份绿色主题的 defaultStyles,再导出 styleFn 根据 props.type === 'error' 切换成红系配色:
const styleFn: NotificationArgsProps['styles'] = ({ props }) => {
if (props.type === 'error') {
return {
...defaultStyles,
root: {
...defaultStyles.root,
backgroundColor: '#fff2f0',
borderColor: '#ffccc7',
boxShadow: '4px 4px 0 #ffccc7',
},
icon: { color: '#cf1322' },
title: { color: '#cf1322' },
description: { color: '#5c0011' },
};
}
return defaultStyles;
};
classNames 的语义节点键名与 styles 完全一致。每个节点的默认效果与视觉含义可在 demo/_semantic.tsx 的可交互预览中看到。
Design Token:用主题令牌定制外观
Notification 属于"组件级 Token"可定制组件。其公开的 ComponentToken 定义在 components/notification/style/index.ts,主要包括:
| Token | 说明 | 默认值 |
|---|---|---|
zIndexPopup |
通知弹层的 z-index | token.zIndexPopupBase + CONTAINER_MAX_OFFSET + 50 |
width |
通知宽度(FAQ 中定制宽度就靠它) | 384 |
progressBg |
自动关闭进度条背景色 | linear-gradient(90deg, colorPrimaryBorderHover, colorPrimary) |
colorSuccessBg |
成功通知容器背景色 | undefined(默认走通用背景) |
colorErrorBg |
错误通知容器背景色 | undefined |
colorInfoBg |
信息通知容器背景色 | undefined |
colorWarningBg |
警告通知容器背景色 | undefined |
此外内部还会从 Alias Token 推导出 notificationBg(默认 colorBgElevated)、内边距、notificationProgressHeight(2)等私有派生 Token。使用时通过 ConfigProvider 的 theme.components.Notification 注入,例如 component-token.tsx 用四种状态的渐变背景让通知卡片区分度更高:
<ConfigProvider
theme={{
components: {
Notification: {
colorSuccessBg: 'linear-gradient(30deg, #d9f7be, #f6ffed)',
colorErrorBg: 'linear-gradient(30deg, #ffccc7, #fff1f0)',
colorInfoBg: 'linear-gradient(30deg, #bae0ff, #e6f4ff)',
colorWarningBg: 'linear-gradient(30deg, #ffffb8, #feffe6)',
},
},
}}
>
<CustomThemeDemo />
</ConfigProvider>
源码视角:静态方法的一次调用背后发生了什么
理解底层机制有助于排查疑难问题。在 components/notification/index.tsx 中可以看到一条完整的调度链:
- 调用排队:
notification.open(config)把任务{ type: 'open', config }push 进模块级taskQueue,然后触发flushNotificationQueue()(见 index.tsx)。 - 延迟挂载:首次调用时,组件通过
document.createDocumentFragment()创建片段,并使用@rc-component/util的render将GlobalHolderWrapper渲染进去;这个"延迟渲染"设计是为了规避同步渲染导致的时序问题。渲染成功后sync到notification.instance,随后继续消费队列。 - 消费任务:队列中每个
open任务都会以{ ...defaultGlobalConfig, ...task.config }合并全局默认值与本次配置后调用底层instance.open;destroy任务同理(flushNotificationQueue)。 - 全局配置同步:
notification.config()通过setNotificationGlobalConfig更新defaultGlobalConfig并调用notification?.sync?.(),让已挂载的 Holder 重新拿到最新全局值(index.tsx)。 - 类型方法注入:
success / error / info / warning通过methods.forEach循环向open注入type,最终在 useNotification.tsx 里根据type查TypeIcon(对应@ant-design/icons的CheckCircleFilled / InfoCircleFilled / CloseCircleFilled / ExclamationCircleFilled / LoadingOutlined,见 PurePanel.tsx)。
同时注意若干默认常量(见 useNotification.tsx):
DEFAULT_DURATION = 4.5:未传duration时默认 4.5 秒自动关闭;DEFAULT_PLACEMENT = 'topRight':默认出现在右上角;DEFAULT_STACK_CONFIG = { offset: 8 }:堆叠通知之间的偏移为 8px,且 style/index.ts 中默认最多折叠展示 3 条(DEFAULT_COLLAPSED_STACK_VISIBLE_COUNT = 3),超出阈值、未展开的通知会被隐藏。
位置偏移通过 CSS 变量 --notification-top / --notification-bottom 落地(见 util.ts),这解释了为何 top/bottom 只需要在 Hooks 配置或全局 config() 中声明一次,所有通知都会自动对齐。
FAQ:三个高频问题
1. 为什么通知里访问不到 context / redux / ConfigProvider 的 locale、prefixCls、theme?
当调用 notification.xxx() 这类静态方法时,antd 会在内部通过 ReactDOM.render(实际为 @rc-component/util 的 render)动态创建 React 实例,它运行在与你业务代码不同的执行上下文中,因此读不到原组件树的 Context。
解决方式:改用 notification.useNotification 拿到 api 实例与 contextHolder,并把 contextHolder 放在需要读取 Context 的 Provider 内部:
const [api, contextHolder] = notification.useNotification();
return (
<Context1.Provider value="Ant">
{/* contextHolder 位于 Context1 内部,api 能读到 Context1 的值 */}
{contextHolder}
<Context2.Provider value="Design">
{/* contextHolder 在 Context2 外部,api 读不到 Context2 的值 */}
</Context2.Provider>
</Context1.Provider>
);
注意:使用 Hooks 时必须把 contextHolder 挂载到 children 中。若无需 Context 关联,可直接使用静态方法。
扩展:官方还推荐直接用 App 包装组件 简化
useNotification等需要手动植入contextHolder的流程。
2. 如何设置静态方法的 prefixCls?
静态方法(notification.open 等)由于脱离组件树,无法读取 ConfigProvider 的 prefixCls。此时应改用 ConfigProvider.config 这一全局配置入口(4.13.0 起)来指定前缀。从 index.tsx 可以看到,静态方法的全局 Holder 外层会被包一层 ConfigProvider,其 prefixCls / iconPrefixCls / theme 取自全局 ConfigProvider.config 的注册值,因此通过该 API 设置的 prefixCls 对静态方法同样生效。
3. 为什么 style={{ width: 'max-content' }} 对 Notification 不生效?
Notification 使用固定宽度布局,以保证堆叠卡片(stack)的视觉一致性,因此 max-content、min-content、fit-content(...) 这类内在尺寸单位在通知外层节点上不受支持。官方推荐两种替代方案:
一是用组件 Token width 统一改宽度(底层默认 384px,见 style/index.ts):
<ConfigProvider
theme={{
components: {
Notification: {
width: 480,
},
},
}}
>
<App />
</ConfigProvider>
二是如果只需要内容按自身尺寸收缩,可以在 title 或 description 里渲染自己的 ReactNode,并把 max-content 加在内部节点上,而不是加在通知根节点上。
结语
Notification 是 antd 反馈体系中灵活度最高的"全局提示"组件之一。工程落地时建议遵循三条主线:优先使用 useNotification Hooks(拿到 Context 能力、规避静态方法在 React 并发模式下的渲染警告);必要时用 notification.config() 或 ConfigProvider 收敛全局默认值(位置、偏移、maxCount、RTL、closeIcon);精细场景用语义化 DOM 与组件 Token 定制外观(进度条、各状态背景、宽度等)。搭配本文讲解的源码调度机制与 FAQ,你可以从容应对大部分 Notification 开发与排障场景。相关组件还可以进一步参考 message(轻量提示)与 App(统一挂载与配置),以便在项目中建立一致的反馈体系。
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 StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00