Ant Design Card 组件完全指南:从基础用法到源码级实现解析
Ant Design Card 组件完全指南从基础用法到源码级实现解析【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-designCard卡片是 Ant Design 数据展示Data Display组中的核心容器组件用于承载与单一主题相关的信息内容内容可以由多种类型、多种尺寸的元素构成。本文以 Card 官方文档 为骨架结合仓库内 Card 组件源码、Grid/Meta 子组件、样式与 Design Token 定义 以及 官方 Demo 集合系统讲解 Card 的全部 API、组合子组件、样式定制方案与底层实现原理。阅读完本文你将能够熟练使用 Card 搭建各类信息容器并深入理解其模块化结构与 Token 定制机制。一、使用场景When To Use当需要将围绕单一主题的内容组织在一起展示时Card 是最合适的选择。卡片内容可以包含多种元素文本、图片、操作按钮、标签页、操作栏等且这些元素类型和尺寸可以自由混排。典型的应用场景包括商品信息卡片封面图 标题 描述 操作后台管理面板中的统计卡片与数据概览文章/媒体列表的展示容器需要分组呈现、可嵌套的信息块。Card 的 API 设计为“容器 命名区块”模式整个卡片由head头部、cover封面、body主体、actions操作区等模块组成每一模块都可以独立定制样式。二、基础用法与核心 APICard 的最小使用方式极其简单Card titleCard titleCard content/Card在此基础上basic.tsx 示例 展示了带标题、右上角附加内容与尺寸切换的完整形态import React from react; import { Card, Space } from antd; const App: React.FC () ( Space directionvertical size{16} Card titleDefault size card extra{a href#More/a} style{{ width: 300 }} pCard content/p pCard content/p pCard content/p /Card Card sizesmall titleSmall size card extra{a href#More/a} style{{ width: 300 }} pCard content/p pCard content/p pCard content/p /Card /Space ); export default App;2.1 Card 属性总表以下属性直接继承自 CardProps 接口与官方文档 API 表一一对应属性说明类型默认值版本actions卡片操作组展示在卡片底部ArrayReactNode-activeTabKey当前激活页签的 keystring-bordered是否展示卡片边框booleantruecover卡片封面ReactNode-defaultActiveTabKey初始化选中页签的 key如果没有设置activeTabKeystring第一个页签的 keyextra卡片右上角的操作区域ReactNode-hoverable鼠标移过时可浮起booleanfalseloading当卡片内容还在加载中时可以用 loading 展示一个占位booleanfalsesize卡片大小default|smalldefaulttabBarExtraContenttab bar 下额外的表达元素ReactNode-tabList页签标题列表TabItemType[]-tabProps透传给内部 Tabs 组件的属性Tabs-title卡片标题ReactNode-type卡片样式类型可设为inner或空string-classNames配置卡片内置模块的 classNameRecordSemanticDOM, string-5.14.0styles配置卡片内置模块的 styleRecordSemanticDOM, string-5.14.0onTabChange页签切换的回调(key) void-2.2 无边框卡片border-less设置bordered{false}即可去掉边框卡片改为使用boxShadowTertiary阴影呈现层次。border-less.tsx 示例Card titleCard title bordered{false} style{{ width: 300 }} pCard content/p pCard content/p pCard content/p /Card从 style/index.ts 的源码可以看到无边框样式正是通过:not(${componentCls}-bordered)选择器将默认border替换为boxShadow: boxShadowTertiary实现的。无边框卡片常配合栅格系统做多列布局in-column.tsx 示例 展示了用Row/Col将无边框卡片排成三列的经典后台布局import { Card, Col, Row } from antd; const App: React.FC () ( Row gutter{16} Col span{8} Card titleCard title bordered{false}Card content/Card /Col Col span{8} Card titleCard title bordered{false}Card content/Card /Col Col span{8} Card titleCard title bordered{false}Card content/Card /Col /Row ); export default App;2.3 极简卡片simple不传title和extra时Card 只渲染主体内容形成无头卡片适合作为纯内容容器。simple.tsx 示例Card style{{ width: 300 }} pCard content/p pCard content/p pCard content/p /Card从 Card.tsx 渲染逻辑 可以看到只有当title、extra或tabs三者至少存在一个时才会渲染head区块这正是极简卡片不出现头部的原因。三、组合子组件Card.Grid 与 Card.MetaCard 通过Card.Grid、Card.Meta两个静态子组件提供组合能力二者在 index.tsx 中被挂载到 Card 上Card.Grid Grid; Card.Meta Meta;3.1 Card.Grid栅格卡片Grid 用于在卡片主体内切分网格适合将多个条目以网格形式展示。其属性定义见 Grid.tsx 源码属性说明类型默认值className容器类名string-hoverable鼠标移过时网格是否浮起booleantruestyle容器样式对象CSSProperties-grid-card.tsx 示例 展示了一个经典的 25% 四列网格布局其中第二个 Grid 显式关闭了 hover 效果const gridStyle: React.CSSProperties { width: 25%, textAlign: center, }; const App: React.FC () ( Card titleCard Title Card.Grid style{gridStyle}Content/Card.Grid Card.Grid hoverable{false} style{gridStyle}Content/Card.Grid Card.Grid style{gridStyle}Content/Card.Grid Card.Grid style{gridStyle}Content/Card.Grid Card.Grid style{gridStyle}Content/Card.Grid Card.Grid style{gridStyle}Content/Card.Grid Card.Grid style{gridStyle}Content/Card.Grid /Card ); export default App;源码层面有两个值得注意的细节网格识别机制Card 在渲染时会遍历children通过element?.type Grid判断是否包含 Grid 子元素Card.tsx命中后为卡片根节点添加ant-card-contain-grid类名使 body 变为display: flex; flex-wrap: wrap的弹性布局style/index.ts。网格边框实现网格之间并非使用border而是通过boxShadow组合四边绘制细线hover 时叠加cardShadow并提升zIndex实现浮起效果genCardGridStyle。3.2 Card.Meta元信息Meta 用于组织卡片的头像avatar、标题title与描述description属性定义见 Meta.tsx 源码属性说明类型默认值avatar头像或图标ReactNode-className容器类名string-description描述内容ReactNode-style容器样式对象CSSProperties-title标题内容ReactNode-Meta 的渲染结构为avatar detail(title description)两段式布局Meta.tsx只有 title 或 description 存在时才渲染 detail 容器。典型用法来自 meta.tsx 示例结合封面与操作栏构成完整的内容卡片import { EditOutlined, EllipsisOutlined, SettingOutlined } from ant-design/icons; import { Avatar, Card } from antd; const { Meta } Card; const App: React.FC () ( Card style{{ width: 300 }} cover{ img altexample srchttps://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png / } actions{[ SettingOutlined keysetting /, EditOutlined keyedit /, EllipsisOutlined keyellipsis /, ]} Meta avatar{Avatar srchttps://api.dicebear.com/7.x/miniavs/svg?seed8 /} titleCard title descriptionThis is the description / /Card ); export default App;3.3 自定义内容flexible-contentCard 的 children 可以是任意 ReactNode。flexible-content.tsx 示例 展示了hoverablecoverMeta的组合——鼠标移过时整卡浮起封面图片自动占满卡片宽度const { Meta } Card; const App: React.FC () ( Card hoverable style{{ width: 240 }} cover{img altexample srchttps://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png /} Meta titleEurope Street beat descriptionwww.instagram.com / /Card );hoverable的浮起效果在 style/index.ts 中定义为box-shadow与border-color的过渡动画悬浮时边框透明、阴影加深。四、加载态与内嵌卡片4.1 加载占位loading数据未就绪时设置loadingCard 内部会用 Skeleton 骨架屏替换主体内容。loading.tsx 示例 用 Switch 动态切换加载态const [loading, setLoading] useStateboolean(true); Card loading{loading} actions{actions} style{{ minWidth: 300 }} Card.Meta avatar{Avatar srchttps://api.dicebear.com/7.x/miniavs/svg?seed1 /} titleCard title description{ pThis is the description/p pThis is the description/p / } / /Card实现上Card.tsx 在loading为真时将 children 包进Skeleton loading active paragraph{{ rows: 4 }} title{false}骨架屏渲染 4 行段落、不显示标题行同时根节点追加ant-card-loading类名以禁用 body 文本选中genCardLoadingStyle。4.2 内嵌卡片typeinner通过typeinner可在卡片内部再嵌一层标题型内容块常用于分组展示。inner.tsx 示例Card titleCard title Card typeinner titleInner Card title extra{a href#More/a} Inner Card content /Card Card style{{ marginTop: 16 }} typeinner titleInner Card title extra{a href#More/a} Inner Card content /Card /Card内嵌样式由 genCardTypeInnerStyle 实现头部背景使用colorFillAlter、标题字号降为fontSizebody 使用紧凑内边距视觉上与外部卡片形成主次层级。五、页签卡片With TabsCard 原生集成 Tabs通过tabList声明页签列表、onTabChange监听切换。完整示例见 tabs.tsxconst [activeTabKey1, setActiveTabKey1] useStatestring(tab1); Card style{{ width: 100% }} titleCard title extra{a href#More/a} tabList{[ { key: tab1, tab: tab1 }, { key: tab2, tab: tab2 }, ]} activeTabKey{activeTabKey1} onTabChange{(key) setActiveTabKey1(key)} {contentList[activeTabKey1]} /Card相关 API 使用要点受控与非受控传入activeTabKey即为受控模式配合onTabChange手动更新不传时使用defaultActiveTabKey作非受控初始值默认选中第一个页签。该逻辑在 Card.tsx 中通过activeKey/defaultActiveKey二选一注入内部 Tabs 实现。tabBarExtraContent在无标题卡片中可用它把extra内容放到 tab bar 右侧见 tabs.tsx 第二个示例的tabBarExtraContent{a href#More/a}。tabProps透传给内部 Tabs 的额外属性如tabProps{{ size: middle }}可调整页签尺寸。onTabChange切换回调参数为被激活页签的 key。仓库测试 index.test.tsx 专门验证了点击 tab2 后回调以tab2被调用。标签写法tabList中每个条目既支持旧字段tab也支持新字段labelCardTabListType已标注tab为 deprecated见 Card.tsx。当存在tabList时根节点会附加ant-card-contain-tabs类名Card.tsx样式上压缩头部高度以便容纳页签栏style/index.ts。六、styles与classNames语义化定制5.14.0从 5.14.0 起Card 支持对内置语义模块进行细粒度样式定制。styles注入内联样式classNames追加类名二者均支持以下模块属性说明版本header设置卡片头部5.14.0body设置卡片主体5.14.0extra设置卡片右上角额外区域5.14.0title设置卡片标题5.14.0actions设置卡片操作区5.14.0cover设置卡片封面5.14.0Card titleCard title classNames{{ header: my-header, body: my-body }} styles{{ header: { background: #f5f5f5 }, body: { padding: 24 } }} Card content /Card实现上Card.tsx 定义了moduleClass与moduleStyle两个辅助函数classNames 通过classNames()合并styles 通过对象展开合并card?.styles?.[moduleName]与自定义值后者优先级更高。重要兼容性提示旧属性headStyle与bodyStyle已被标记为 deprecated源码会在开发环境下通过devUseWarning输出弃用警告建议迁移到styles.header/styles.bodyCard.tsx。七、Design Token主题定制Card 是完整的 Token 化组件ComponentTokenTable componentCard在官方文档中自动生成全部 Token 表格。从 style/index.ts 的 ComponentToken 接口 与 prepareComponentToken 默认值 可以确认以下可定制 TokenToken说明默认值headerBg卡片头部背景色transparent透明headerFontSize卡片头部文字大小fontSizeLGheaderFontSizeSM小号卡片头部文字大小fontSizeheaderHeight卡片头部高度fontSizeLG × lineHeightLG padding × 2headerHeightSM小号卡片头部高度fontSize × lineHeight paddingXS × 2actionsBg操作区背景色colorBgContaineractionsLiMargin操作区每一项的外间距paddingSM 0tabsMarginBottom内置标签页组件下间距-(padding lineWidth)extraColor额外区文字颜色colorText在业务中通过 ConfigProvider 覆盖 Tokencomponent-token.tsx 示例 演示了完整定制import { Card, ConfigProvider } from antd; export default () ( ConfigProvider theme{{ components: { Card: { headerBg: #e6f4ff, headerFontSize: 20, headerFontSizeSM: 20, headerHeight: 60, headerHeightSM: 60, actionsBg: #e6f4ff, actionsLiMargin: 2px 0, tabsMarginBottom: 0, extraColor: rgba(0,0,0,0.25), }, }, }} Card titleCard title actions{[ SettingOutlined keysetting /, EditOutlined keyedit /, EllipsisOutlined keyellipsis /, ]} extraMore tabList{[ { key: tab1, label: tab1 }, { key: tab2, label: tab2 }, ]} pCard content/p /Card Card sizesmall titleSmall size card extra{a href#More/a} style{{ width: 300 }} pCard content/p /Card /ConfigProvider );Token 的生效链路为genStyleHooks(Card, ...)将prepareComponentToken生成的默认值合并进主题 Token再由mergeToken注入cardShadowboxShadowCard、cardPaddingBasepaddingLG、cardPaddingSM固定 12px、cardActionsIconSizefontSize等派生 Tokenstyle/index.ts。此外头部高度同时受size影响small尺寸走headerHeightSM/cardPaddingSMgenCardSizeStyle这也解释了headerFontSizeSM、headerHeightSM成对存在的原因。八、从源码理解渲染结构与样式模块综合 Card.tsx 的最终渲染输出一个完整 Card 的 DOM 结构为div classant-card [ant-card-bordered] [ant-card-hoverable] [ant-card-loading] ... div classant-card-head !-- 仅当 title/extra/tabs 存在时渲染 -- div classant-card-head-wrapper div classant-card-head-title…/div div classant-card-extra…/div /div div classant-card-head-tabs…Tabs…/div /div div classant-card-cover…/div !-- 仅当 cover 存在时渲染 -- div classant-card-body…children 或 Skeleton…/div ul classant-card-actions !-- 仅当 actions.length 0 时渲染 -- li stylewidth: 33.33%span…/span/li … /ul /div几个值得关注的实现细节操作栏等宽布局ActionNode按100 / actions.length为每个li分配宽度Card.tsx因此操作按钮数量变化时自动均分样式层还通过borderInlineEnd在相邻项之间绘制分隔线style/index.ts。通用属性透传Card 继承React.HTMLAttributesHTMLDivElementonTabChange会被omit掉以免泄漏到 DOMCard.tsx其余属性如id、aria-*直接透传到根 div。RTL 支持当 ConfigProvider 的direction为rtl时自动追加ant-card-rtl类名Card.tsx样式文件也提供了对应的 RTL 规则style/index.ts仓库的 rtlTest 覆盖了该场景。大小写兼容size通过useSize与 ConfigProvider 的全局 size 合并Card.tsx即未显式指定时继承全局组件尺寸页签大小也随之联动default → largesmall → small。九、常用 API 快速参考通用属性除 Card 自身 API 外所有组件共享的通用属性可参考 Common props 文档。Tabs 联动tabList的类型定义TabItemType与tabProps的TabsProps均来自 Tabs 组件如需深度定制页签行为如居中、禁用、图标页签可查阅该文档。相关示例索引全部 12 个官方示例位于 components/card/demo 目录覆盖基础卡片、无边框、极简、自定义内容、栅格布局、加载态、网格卡片、内嵌卡片、页签卡片、Meta 组合与 Token 定制每个示例均配套独立的 Markdown 说明。【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考