尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Ant Design App 组件实战:用 App.useApp 获取 message、notification、modal 实例

Ant Design App 组件实战:用 App.useApp 获取 message、notification、modal 实例 Ant Design App 组件实战用 App.useApp 获取 message、notification、modal 实例【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design本文围绕 Ant DesignApp组件最核心的能力——通过App.useApp()获取message、notification、modal三个实例即官方示例 基本用法 所述的主题展开先完整走一遍官方 demo 的实战代码再结合仓库源码剖析这三个实例是如何被创建并通过 React Context 下发的最后说明使用约束与版本前提帮助你在业务项目中稳定地以 Hooks 方式消费全局提示能力。一、核心命题获取 message、notification、modal 实例基本用法示例说明 对basic.tsx这个 demo 的概括只有一句话获取message、notification、modal实例。这句话背后是 Ant Design 对全局提示组件的一次架构演进早期做法是导入静态方法message.success()、notification.info()、Modal.confirm()但它们游离于 React 树之外无法消费ConfigProvider的theme、locale等上下文需要手动植入contextHolder5.x 引入的App包裹组件则把这三个能力统一收口为可消费 Context 的实例官方文档 App 组件介绍 中何时使用一节明确了两点提供可消费 React context 的静态方法简化useMessage等方法需要手动植入contextHolder的问题以及提供基于.ant-app的默认重置样式。适用前提该组件自antd5.1.0起提供message/notification全局配置属性自5.3.0起提供。二、官方 basic 示例逐行解析完整示例位于 basic.tsx结构上是入口组件包裹 App 子页面消费实例两层import React from react; import { App, Button, Space } from antd; // Sub page const Page: React.FC () { const { message, modal, notification } App.useApp(); const showMessage () { message.success(Success!); }; const showModal () { modal.warning({ title: This is a warning message, content: some messages...some messages..., }); }; const showNotification () { notification.info({ title: Notification topLeft, description: Hello, Ant Design!!, placement: topLeft, }); }; return ( Space wrap Button typeprimary onClick{showMessage}Open message/Button Button typeprimary onClick{showModal}Open modal/Button Button typeprimary onClick{showNotification}Open notification/Button /Space ); }; // Entry component export default () ( App Page / /App );关键要点App.useApp()是唯一取实例的入口。在Page内一次解构出message、modal、notification三个实例之后以方法调用触发全局提示message.success()、modal.warning({ ... })、notification.info({ ... })用法与静态方法几乎一致但实例感知了组件树上下文。必须在App之内消费。官方文档强调App.useApp 必须在 App 之下方可使用。demo 中Page作为App的子节点挂载正是这一约束的标准写法同时官方推荐在应用顶层包裹App保证整棵子树可用。notification支持placement定位。示例中placement: topLeft让通知出现在左上角这是NotificationInstance实例方法的原生参数。App默认渲染为div。从 AppProps 定义可见component默认值是div即App会在页面中产生一个带.ant-app类名的容器节点。三、源码剖析实例是如何被创建并下发的3.1 App 组件内部一次创建、三处下发App.tsx 的渲染逻辑解释了 basic 示例能工作的完整链路const [messageApi, messageContextHolder] useMessage(mergedAppConfig.message); const [notificationApi, notificationContextHolder] useNotification( mergedAppConfig.notification, ); const [ModalApi, ModalContextHolder] useModal();App组件内部分别调用 useMessage、useNotification 与 useModal 三个 Hook每个 Hook 返回一对结果Api如messageApi即useApp()消费到的实例对象对应接口定义中的MessageInstance/NotificationInstance/ModalHookAPI见 context.tsContextHolder需要挂载到 DOM 上的占位节点实际渲染时被显式插入到子节点之前Component {...rootProps} {ModalContextHolder} {messageContextHolder} {notificationContextHolder} {children} /Component从源码结构看这三个contextHolder正是静态方法需要手动植入 contextHolder这一历史痛点被App自动化的体现——使用者在 basic 示例里完全感知不到 holder 的存在。3.2 useApp只是一个 useContext 薄封装useApp.ts 的完整实现只有一行const useApp () React.useContextuseAppProps(AppContext);而 index.tsx 通过复合组件的方式把 Hook 挂到了App静态属性上App.useApp useApp这正是调用形式为App.useApp()而非import { useApp }的原因。默认值被定义为三个空对象{}所以脱离App包裹调用useApp()不会报错但拿到的实例是空的——这解释了为什么文档特别强调必须在 App 之下方可使用。3.3 配置合并外层 ConfigProvider/App 配置如何生效App还支持接收message、notification两个全局配置对象App.tsx 中会将其与上层AppConfigContext的值做浅合并const mergedAppConfig React.useMemoAppConfig( () ({ message: { ...appConfig.message, ...message }, notification: { ...appConfig.notification, ...notification }, }), [message, notification, appConfig.message, appConfig.notification], );合并后的配置随即传入useMessage(mergedAppConfig.message)和useNotification(mergedAppConfig.notification)。仓库内另一个演示 config.tsx 展示了该机制的实际用法App message{{ maxCount: 1 }} notification{{ placement: bottomLeft }} Page / /App即message属性接受MessageConfig如限制同屏最大条数maxCountnotification属性接受NotificationConfig如默认位置placement所有经由该App子树发出的提示都会默认带上这些配置。3.4 样式侧.ant-app重置样式从哪来basic 示例中App渲染出的div会带上 hashId、.ant-app前缀类名以及 RTL 场景下的.ant-app-rtl。样式生成逻辑见 style/index.tsconst genBaseStyle: GenerateStyleAppToken, CSSObject (token) { const { componentCls, colorText, fontSize, lineHeight, fontFamily } token; return { [componentCls]: { color: colorText, fontSize, lineHeight, fontFamily, [${componentCls}-rtl]: { direction: rtl }, }, }; };也就是说App根节点用主题 TokencolorText、fontSize、lineHeight、fontFamily为子树提供基础文本样式让裸写的原生元素如示例中的Button外的任意文本也符合 antd 规范——这就是何时使用中提到的第二项能力。这也解释了为什么文档要求App与ConfigProvider成对出现且位于其下方只有处于ConfigProvider子树内getPrefixCls与主题 Token 才能正确解析示例的标准嵌套是ConfigProvider theme{{ ... }} App ... /App /ConfigProvider四、进阶用法让全局状态如 redux也能触发提示basic 示例只覆盖了页面内消费的场景。当提示需要被路由外的全局 store、工具函数触发时官方文档给出了全局场景方案用一个隐藏组件在顶层调用App.useApp()并把实例导出供任意位置 import 使用// Entry component import { App } from antd; import type { MessageInstance } from antd/es/message/interface; import type { ModalStaticFunctions } from antd/es/modal/confirm; import type { NotificationInstance } from antd/es/notification/interface; let message: MessageInstance; let notification: NotificationInstance; let modal: OmitModalStaticFunctions, warn; export default () { const staticFunction App.useApp(); message staticFunction.message; modal staticFunction.modal; notification staticFunction.notification; return null; }; export { message, notification, modal };子页面随后通过import { message } from ./store直接调用message.success(Success!)。这一技巧的本质仍是 basic 示例的同一原理App.useApp()从 Context 取值只是把取值的时机提前到了应用入口。五、注意事项与版本差异component{false}会失去样式承载节点。App的component属性5.11.0起可改为其他组件类型设为false时不创建 DOM 节点、只提供上下文此时className、rootClassName、style均无法生效。App.tsx 中有两条开发期devWarning专门拦截这类误用cssVar 模式下component必须为有效组件、component{false}时传ref会告警。文档 FAQ 也指出Ant Design v6 默认使用 CSS 变量而 CSS 变量需要有效 HTML 元素承载类名因此在 CSS Var 模式下建议保留默认div。尽量避免嵌套App。除非确有隔离上下文的必要嵌套会重复创建 holder 节点且内层配置会覆盖外层见 3.3 的合并逻辑内层 props 优先级更高。验证依据。该 demo 被 demo.test.ts 纳入仓库的通用 demo 快照测试demoTest(app)示例代码与快照 index.test.tsx.snap 共同保证 basic 示例的渲染输出稳定可回归。六、小结与延伸阅读围绕 basic.md 这一主题核心结论可以压缩为三条App在应用顶层包裹子树内部一次性创建message、notification、modal三个 API 实例并自动挂载各自的 contextHolder子组件用App.useApp()本质是useContext(AppContext)取回实例以实例方法替代静态方法调用天然继承ConfigProvider的主题与上下文需要全局化如 redux 场景时在入口组件中调用一次useApp()并导出实例即可。可继续深入的文件App 组件完整文档含 API 与 FAQ、App 实现、Context 与类型定义、样式生成、以及配套的 Hooks 配置示例。【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/GitHub_Trending/an/ant-design创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表