资讯动态

umi 示例项目中的 Ant Design Pro 业务组件实战:Footer、HeaderSearch、NoticeIcon 与 RightContent 的实现解析

发布时间:2026/9/14 7:32:40 来源:尧图企业网站定制
umi 示例项目中的 Ant Design Pro 业务组件实战:Footer、HeaderSearch、NoticeIcon 与 RightContent 的实现解析【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi在 umi 仓库的examples/antd-pro-create示例工程中,有一份专门用于指导业务开发的文档 业务组件。它汇总了 Ant Design Pro 在实际业务中真实需要、但又不适合作为组件库的一类组件:页脚、头部下拉、头部搜索、通知中心和右侧内容区组合。本篇以该文档为骨架,完整继承其全部用法示例与 API 参数说明,并逐一到示例工程源码中印证每个组件的实现原理——useMergedState受控/非受控双模式、getPopupContainer的移动端适配、Tab 化通知列表的数据聚合逻辑——读完后可直接在类似中后台项目中复用这些组件,或理解其底层设计。Footer 页脚组件文档指出,Footer 组件自带了一些 Pro 的配置,你一般都需要改掉它的信息。最简用法如下:/** * background: #f0f2f5 */ import Footer from /components/Footer; export default () Footer /;结合源码 Footer/index.tsx 可以看到,它本质上是对ant-design/pro-components中DefaultFooter的薄封装:通过useIntl().formatMessage读取app.copyright.produced文案(默认蚂蚁集团体验技术部出品),版权年份由new Date().getFullYear()动态计算;links中内置了 Ant Design Pro、GitHub、Ant Design 三个链接,且均设置blankTarget: true在新窗口打开;copyright最终拼为${currentYear} ${defaultMessage}。因此实际项目中改掉它的信息通常只需要两步:替换formatMessage的 defaultMessage 与links数组。另外,该示例工程还配有一条端到端用例 baseLayout.e2e.spec.ts:它遍历 routes 中的全部路由,在每个页面断言document.getElementsByTagName(footer).length 0,即 Footer 是布局级组件,在每条路由下都必须渲染,这为页脚是否接入成功提供了可验证的依据。HeaderDropdown 头部下拉列表文档说明:HeaderDropdown 是 antdDropdown的封装,增加了移动端的特殊处理,用法与 antd 相同:/** * background: #f0f2f5 */ import HeaderDropdown from /components/HeaderDropdown; import { Button, Menu } from antd; export default () { const menuHeaderDropdown ( Menu selectedKeys{[]} Menu.Item keycenter个人中心/Menu.Item Menu.Item keysettings个人设置/Menu.Item Menu.Divider / Menu.Item keylogout退出登录/Menu.Item /Menu ); return ( HeaderDropdown overlay{menuHeaderDropdown} Buttonhover 展示菜单/Button /HeaderDropdown ); };从 HeaderDropdown/index.tsx 的源码看,封装只做了两件事,却正是移动端特殊处理的关键:getPopupContainer重定向:通过getPopupContainer{(target) target.parentElement || document.body}把弹层挂载到触发元素的父节点而非body,避免在移动端被其他全屏元素遮挡、以及定位计算异常;样式类合并:overlayClassName与内部styles.container用classNames合并,外部传入的类名不会覆盖内置定位样式。其余所有属性通过OmitDropDownProps, overlay透传给 antdDropdown,所以文档中用法也是相同的这一说法在类型层面即得到保证。HeaderSearch 头部搜索框文档将其描述为一个带补全数据的输入框,支持收起和展开 Input:/** * background: #f0f2f5 */ import HeaderSearch from /components/HeaderSearch; export default () { return ( HeaderSearch placeholder站内搜索 defaultValueumi ui options{[ { label: Ant Design Pro, value: Ant Design Pro }, { label: Ant Design, value: Ant Design, }, { label: Pro Table, value: Pro Table, }, { label: Pro Layout, value: Pro Layout, }, ]} onSearch{(value) { console.log(input, value); }} / ); };API参数说明类型默认值value输入框的值string-onChange值修改后触发(value?: string) void-onSearch查询后触发(value?: string) void-options选项菜单的列表{label,value}[]-defaultVisible输入框默认是否显示,只有第一次生效boolean-visible输入框是否显示boolean-onVisibleChange输入框显示隐藏的回调函数(visible: boolean) void-再看 HeaderSearch/index.tsx 的实现,上述 API 行为都能找到对应代码:受控/非受控双模式:输入值value与展开态searchMode都使用rc-util的useMergedState管理,分别绑定value/defaultValue与visible/defaultVisible。defaultVisible只有第一次生效的语义正来自useMergedState的初始化机制;收起/展开交互:点击搜索图标触发setSearchMode(true)并对inputRef.current.focus()聚焦;Input的onBlur则执行setSearchMode(false)收起。输入框宽度变化依赖 CSS 过渡(index.less),onTransitionEnd中判断propertyName width后再回调onVisibleChange,保证外部拿到的是过渡完成后的真实状态;补全与提交:AutoComplete渲染options提供下拉补全,onChange时把补全值同步回setValue;按下Enter键才调用onSearch(value),即值变化与查询提交是两个独立时机。这种图标常驻、输入框按需展开的设计,正是头部空间有限场景下的典型解法。NoticeIcon 通知工具文档说明:通知工具提供一个展示多种通知信息的界面,支持以 Tab 形式承载多个通知列表:/** * background: #f0f2f5 */ import NoticeIcon from /components/NoticeIcon/NoticeIcon; import { message } from antd; export default () { const list [ { id: 000000001, avatar: https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png, title: 你收到了 14 份新周报, datetime: 2017-08-09, type: notification, }, { id: 000000002, avatar: https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png, title: 你推荐的 曲妮妮 已通过第三轮面试, datetime: 2017-08-08, type: notification, }, ]; return ( NoticeIcon count{10} onItemClick{(item) { message.info(${item.title} 被点击了); }} onClear{(title: string, key: string) message.info(点击了清空更多)} loading{false} clearText清空 viewMoreText查看更多 onViewMore{() message.info(点击了查看更多)} clearClose NoticeIcon.Tab tabKeynotification count{2} list{list} title通知 emptyText你已查看所有通知 showViewMore / NoticeIcon.Tab tabKeymessage count{2} list{list} title消息 emptyText您已读完所有消息 showViewMore / NoticeIcon.Tab tabKeyevent title待办 emptyText你已完成所有待办 count{2} list{list} showViewMore / /NoticeIcon ); };NoticeIcon API参数说明类型默认值count有多少未读通知number-bell铃铛的图表ReactNode-onClear点击清空数据按钮(tabName: string, tabKey: string) void-onItemClick未读消息列被点击(item: API.NoticeIconData, tabProps: NoticeIconTabProps) void-onViewMore查看更多的按钮点击(tabProps: NoticeIconTabProps, e: MouseEvent) void-onTabChange通知 Tab 的切换(tabTile: string) void;-popupVisible通知显示是否展示boolean-onPopupVisibleChange通知信息显示隐藏的回调函数(visible: boolean) void-clearText清空按钮的文字string-viewMoreText查看更多的按钮文字string-clearClose展示清空按钮boolean-emptyImage列表为空时的兜底展示ReactNode-NoticeIcon.Tab API参数说明类型默认值count有多少未读通知number-title通知 Tab 的标题ReactNode-showClear展示清除按钮booleantrueshowViewMore展示加载更booleantruetabKeyTab 的唯一 keystring-onClick子项的单击事件(item: API.NoticeIconData) void-onClear清楚按钮的点击()void-emptyText为空的时候测试()void-viewMoreText查看更多的按钮文字string-onViewMore查看更多的按钮点击( e: MouseEvent) void-list通知信息的列表API.NoticeIconData-NoticeIconDataexport type NoticeIconData { id: string; key: string; avatar: string; title: string; datetime: string; type: string; read?: boolean; description: string; clickClose?: boolean; extra: any; status: string; }源码实现:Tab 组装与弹层控制NoticeIcon/NoticeIcon.tsx 中有几个值得注意的设计:NoticeIcon.Tab即NoticeList:组件末尾执行NoticeIcon.Tab NoticeList;,父级传入的每个NoticeIcon.Tab子元素在getNotificationBox中被React.Children.forEach遍历,取其list/title/count/tabKey/showClear/showViewMoreprops 包装进 antdTabs的TabPane;Tab 标题自动带数量:const msgCount count || count 0 ? count : len;,若未显式传count则回退为list.length,标题渲染为${title} (${msgCount});弹层基于 HeaderDropdown 实现:popupVisible同样用useMergedState管理(默认收起),弹层以trigger{[click]}的 HeaderDropdown 承载,placementbottomRight;loading为 true 时外层包一层Spin(delay 300);空态兜底:NoticeList在 NoticeIcon/NoticeList.tsx 中处理,list为空时展示空态图片与emptyText;avatar既可以是 URL 字符串(渲染Avatar),也可以是自定义节点;已读项通过item.read添加样式类区分;底部bottomBar按showClear/showViewMore分别渲染清空 {title}与viewMoreText按钮。真实接入示例:从接口数据到 Tab 分组文档示例是静态数据写法,而工程中真正使用的版本是 NoticeIcon/index.tsx,它演示了组件与 umi 数据层的完整接线方式,值得作为二次开发的参照:通过useRequest(getNotices)(来自 services/ant-design-pro/api.ts)拉取通知列表;getNoticeData做三件事:moment(notice.datetime).fromNow()把日期转成相对时间、key id补全 React key、用 lodashgroupBy(notices, type)按类型拆成 notification/message/event 三组;getUnreadData统计每组!item.read的数量作为各 Tab 的count;onItemClick中把单条通知置为read: true,onClear中把整个type key分组全部置已读,铃铛总数取自initialState.currentUser.unreadCount。相关类型(如API.NoticeIconItem)定义在 services/ant-design-pro/typings.d.ts,即文档 API 表中API.NoticeIconData的来源。RightContent 右侧内容区组合文档最后给出 RightContent 的定位:它是以上几个组件的组合,同时新增了 plugins 的SelectLang插件:Space HeaderSearch placeholder站内搜索 defaultValueumi ui options{[ { label: a hrefhttps://umijs.org/zh/guide/umi-ui.htmlumi ui/a, value: umi ui }, { label: a hrefnext.ant.designAnt Design/a, value: Ant Design, }, { label: a hrefhttps://protable.ant.design/Pro Table/a, value: Pro Table, }, { label: a hrefhttps://prolayout.ant.design/Pro Layout/a, value: Pro Layout, }, ]} / Tooltip title使用文档 span className{styles.action} onClick{() { window.location.href https://pro.ant.design/docs/getting-started; }} QuestionCircleOutlined / /span /Tooltip Avatar / {REACT_APP_ENV ( span Tag color{ENVTagColor[REACT_APP_ENV]}{REACT_APP_ENV}/Tag /span )} SelectLang className{styles.action} / /Space对照 RightContent/index.tsx 的当前实现,有几个补充点:组件读取useModel(initialState)中的settings,当navTheme realDark layout top或layout mix时,给容器追加dark样式类,保证深色导航下搜索框与图标的可见性;文档中的Avatar对应 AvatarDropdown.tsx:它同样基于 HeaderDropdown,菜单项含个人中心/个人设置/退出登录;点击退出时先flushSync清空initialState.currentUser,再调用outLogin(),并在未指定redirect参数时把当前pathname search拼进登录页跳转,保证登录后回到原页面;SelectLang由umijs/max插件提供(示例工程的 locales 目录即其数据来源),是文档所说的plugins 的 SelectLang 插件。小结:何时使用这些业务组件回到文档开头的判断标准——这些组件不适合作为组件库,但是在业务中却真实需要。从examples/antd-pro-create的实现看,它们的共同特征是:强依赖 antd / ProComponents 的特定行为(弹层挂载、Tab 组装、受控合并状态),但本身不含复杂业务逻辑,适合作为页面级骨架组件直接拷入自己的中后台项目;需要调整的主要是文案(links、emptyText)、数据源(getNotices)以及环境信息(版权、文档链接)。若要验证布局级组件在全部路由下的渲染正确性,工程内置的 Playwright 用例 baseLayout.e2e.spec.ts 提供了可直接参考的断言写法。【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价