Ant Design Descriptions 描述列表组件完全指南:从 items 配置到响应式布局与源码实现
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
导读
本文以 Ant Design(antd)Descriptions(描述列表)组件为核心,系统讲解如何在详情页中高效展示只读字段组合。你将掌握items配置式写法与Descriptions.Item子组件写法的差异与取舍、column/span的响应式规则、bordered/size/layout等全部 API 参数,并通过阅读 组件入口源码、行布局算法 与 单元格渲染,理解其底层实现原理,最终能独立构建出带边框、垂直、响应式的专业详情页。
何时使用 Descriptions
Descriptions组件常用于详情页的信息展示,用于在页面上以「标签 + 内容」的规整列表形式呈现一组只读字段,例如订单详情、用户资料、云资源实例配置等场景。与Table相比,它不承载复杂交互,专注静态信息的视觉组织;与Card+ 手工排版相比,它内置了列数控制、边框、标签对齐与响应式能力,开箱即用。
从 组件实现 可以看出,Descriptions 最终渲染为一个<table>结构(prefixCls-view包裹),将数据以行、列的方式排布,语义上天然适合「字段-值」型只读信息的展示。
两种数据写法:items 配置式与 Item 子组件式
items 配置式(>= 5.8.0 推荐)
自 antd 5.8.0 起,官方推荐使用items配置数组写法,数据与渲染分离,结构更清晰:
// >= 5.8.0 可用,推荐的写法 const items: DescriptionsProps['items'] = [ { key: '1', label: 'UserName', children: <p>Zhou Maomao</p>, }, { key: '2', label: 'Telephone', children: <p>1810000000</p>, }, { key: '3', label: 'Live', children: <p>Hangzhou, Zhejiang</p>, }, { key: '4', label: 'Remark', children: <p>empty</p>, }, { key: '5', label: 'Address', children: <p>No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China</p>, }, ]; <Descriptions title="User Info" items={items} />;从源码看,DescriptionsItemType 类型允许每个 item 携带key、label、children、span(数字或响应式对象)、labelStyle、contentStyle、className、style等字段,组件内部 通过useItems(screens, items, children)优先消费items。
Item 子组件式(< 5.8.0 兼容写法)
对于 5.8.0 以下版本,或偏好 JSX 声明式写法的场景,可以使用Descriptions.Item子组件:
// <5.8.0 可用,>=5.8.0 时不推荐 <Descriptions title="User Info"> <Descriptions.Item label="UserName">Zhou Maomao</Descriptions.Item> <Descriptions.Item label="Telephone">1810000000</Descriptions.Item> <Descriptions.Item label="Live">Hangzhou, Zhejiang</Descriptions.Item> <Descriptions.Item label="Remark">empty</Descriptions.Item> <Descriptions.Item label="Address"> No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China </Descriptions.Item> </Descriptions>;有趣的是,Item.ts 中的DescriptionsItem本身并不渲染任何 DOM,它只是把children原样返回(({ children }) => children),真正的数据采集发生在 useItems.ts 中:通过rc-util的toArray遍历子节点,再{ ...node?.props, key: node.key }把每个<Descriptions.Item>的 props 拍平成与items数组同构的数据。因此两种写法在渲染层完全等价,items只是把这种「运行时采集」提前到了业务代码中。
Descriptions 完整 API 参数详解
Descriptions 属性总览
以下表格完整覆盖 index.zh-CN.md 中定义的 API,并补充了源码中的行为细节。
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| bordered | 是否展示边框 | boolean | false | |
| colon | 配置Descriptions.Item的colon的默认值。表示是否显示 label 后面的冒号 | boolean | true | |
| column | 一行的DescriptionItems数量,可以写成像素值或支持响应式的对象写法{ xs: 8, sm: 16, md: 24} | number |Record<Breakpoint, number> | 3 | |
| contentStyle | 自定义内容样式 | CSSProperties | - | 4.10.0 |
| extra | 描述列表的操作区域,显示在右上方 | ReactNode | - | 4.5.0 |
| items | 描述列表项内容 | DescriptionsItem[] | - | 5.8.0 |
| labelStyle | 自定义标签样式 | CSSProperties | - | 4.10.0 |
| layout | 描述布局 | horizontal|vertical | horizontal | |
| size | 设置列表的大小。可以设置为middle、small,或不填(只有设置bordered={true}生效) | default|middle|small | - | |
| title | 描述列表的标题,显示在最顶部 | ReactNode | - |
DescriptionItem 属性
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| contentStyle | 自定义内容样式 | CSSProperties | - | 4.9.0 |
| label | 内容的描述 | ReactNode | - | |
| labelStyle | 自定义标签样式 | CSSProperties | - | 4.9.0 |
| span | 包含列的数量 | number |Screens | 1 | screens: 5.9.0 |
span 语义说明:
span是Description.Item的数量,span={2}会占用两个DescriptionItem的宽度。当同时配置style和labelStyle(或contentStyle)时,两者会同时作用;样式冲突时,后者会覆盖前者。
关键参数源码级解读
- column 的响应式解析:组件实现 中通过
matchScreen(screens, { ...DEFAULT_COLUMN_MAP, ...column })合并用户配置与默认映射,未命中任何断点时兜底为3。constant.ts 定义了各断点默认列数:xxl: 3、xl: 3、lg: 3、md: 3、sm: 2、xs: 1——即默认情况下,小屏手机每行 1 项,平板每行 2 项,桌面及以上每行 3 项。 - bordered 的渲染分支:bordered 模式下每个 item 是独立的一个
<th>/<td>单元格;非 bordered 模式下 label 与 content 被合并进同一个<td>的item-container容器内,用两个<span>展示(见 Cell.tsx)。 - size 的生效条件:从源码看,
mergedSize通过useSize获取(继承 ConfigProvider 的组件尺寸),并仅在非default时追加${prefixCls}-${mergedSize}类名。文档明确说明size只有在设置bordered={true}时才生效,因此无边框模式下设置 size 不会产生视觉差异。 - title 与 extra 的布局:组件实现 中,当
title或extra存在时渲染descriptions-header头部分区,title居左、extra居右,常用于放置「编辑」「详情」等操作按钮。
实战示例:从基本用法到复杂场景
基本用法
最简用法直接传入title与items,参见 demo/basic.tsx:
import React from 'react'; import { Descriptions } from 'antd'; import type { DescriptionsProps } from 'antd'; const items: DescriptionsProps['items'] = [ { key: '1', label: 'UserName', children: 'Zhou Maomao' }, { key: '2', label: 'Telephone', children: '1810000000' }, { key: '3', label: 'Live', children: 'Hangzhou, Zhejiang' }, { key: '4', label: 'Remark', children: 'empty' }, { key: '5', label: 'Address', children: 'No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China' }, ]; const App: React.FC = () => <Descriptions title="User Info" items={items} />; export default App;带边框的 Descriptions
设置bordered后,label 与 content 拥有独立单元格和边框,适合需要强调字段归属的信息密度较高的场景,完整示例见 demo/border.tsx。注意其中span的用法:Usage Time设置span: 2、Status设置span: 3,实现跨列占位:
const items: DescriptionsProps['items'] = [ { key: '5', label: 'Usage Time', children: '2019-04-24 18:00:00', span: 2 }, { key: '6', label: 'Status', children: <Badge status="processing" text="Running" />, span: 3 }, // ... ]; const App: React.FC = () => <Descriptions title="User Info" bordered items={items} />;垂直布局(vertical)
设置layout="vertical"后,label 在上、content 在下。从 Row.tsx 可以看出,垂直模式将一行拆成两个<tr>:label 行(th)与 content 行(td),典型示例如下(完整见 demo/vertical.tsx):
const items: DescriptionsProps['items'] = [ { key: '1', label: 'UserName', children: 'Zhou Maomao' }, { key: '4', label: 'Address', span: 2, children: 'No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China' }, // ... ]; const App: React.FC = () => <Descriptions title="User Info" layout="vertical" items={items} />;垂直布局同样可以叠加bordered(参见 demo/vertical-border.tsx),并在Responsive案例中与响应式 column 组合使用。
响应式列数与响应式 span
column与span都支持断点对象写法。column控制整表每行列数,span控制单个 item 占用的列数,二者可同时使用。以下示例来自 demo/responsive.tsx:column在手机上 1 列、桌面 4 列,同时部分 item 的span按断点变化:
const items: DescriptionsProps['items'] = [ { label: 'Product', children: 'Cloud Database' }, { label: 'Billing', children: 'Prepaid' }, { label: 'Time', children: '18:00:00' }, { label: 'Amount', children: '$80.00' }, { label: 'Discount', span: { xl: 2, xxl: 2 }, children: '$20.00' }, { label: 'Official', span: { xl: 2, xxl: 2 }, children: '$60.00' }, { label: 'Config Info', span: { xs: 1, sm: 2, md: 3, lg: 3, xl: 2, xxl: 2 }, children: ( <> Data disk type: MongoDB <br /> Database version: 3.4 <br /> Package: dds.mongo.mid </> ), }, // ... ]; const App: React.FC = () => ( <Descriptions title="Responsive Descriptions" bordered column={{ xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }} items={items} /> );响应式span的解析同样发生在 useItems.ts:当span是对象时,通过matchScreen(screens, span)依据当前视口断点换算为实际列数;当span为数字时直接透传。注意span的响应式对象写法自 5.9.0 起支持。
自定义尺寸
设置size="small"或size="middle"可调整表格内边距与字号,仅在bordered下生效,参见 demo/size.tsx。若不传size,会继承 ConfigProvider 全局配置的组件尺寸。
自定义 label / content 样式
labelStyle与contentStyle既可以在Descriptions上统一设置(作用所有 item,见 demo/style.tsx),也可以在单个 item 上单独覆盖。合并逻辑位于 Cell.tsx 与 Row.tsx:渲染时通过{ ...rootLabelStyle, ...labelStyle }逐级合并,item 级样式优先级更高;此外二者经 DescriptionsContext 从顶层向单元格传递,这也是组件内共享样式配置的实现通道。
复杂文本与间距控制
复杂内容(如多行文本、换行、富节点)在 bordered 模式下表现更规整,相关调试示例见 demo/text.tsx 与 demo/padding.tsx。children接受任意ReactNode,可以嵌入<Badge>、<Tag>、<br />等组合元素,如上面 border 示例中的<Badge status="processing" text="Running" />。
底层实现原理:从数据到表格的完整流水线
Descriptions 的渲染流程可以概括为「列数合并 → 数据归一化 → 行布局 → 单元格渲染」四个阶段,对应源码中的四个关键模块:
- 列数合并(column):组件实现 通过
useMemo合并DEFAULT_COLUMN_MAP与用户column配置,得到当前断点下的mergedColumn;useBreakpoint负责订阅视口断点变化,这也是响应式能力的来源。 - 数据归一化(items/children):useItems.ts 优先取
items,否则将children中的<Descriptions.Item>拍平为同一数据结构,再统一完成响应式span解析,输出InternalDescriptionsItemType[]。 - 行布局算法(useRow):useRow.ts 按
mergedColumn把扁平数组切分为二维行数组:逐个 item 累加span,当前行剩余列数不足时换行;末尾 item 自动用剩余列数填充其span(getFilledItem)。当出现「某行 span 之和与 column 不匹配」的情况时,开发环境下会通过devUseWarning输出警告:Sum of column span in a line not match column of Descriptions.——这意味着你可以借助该警告在开发期快速定位跨行配置错误。 - 单元格渲染(Row / Cell):Row.tsx 依据
layout(horizontal / vertical)与bordered决定 DOM 结构:垂直模式拆分为 label、content 两个<tr>;水平模式单<tr>内完成 label+content 组合。最终由 Cell.tsx 输出<th>/<td>并计算colSpan。
上述阶段均有对应的单元测试覆盖,例如 index.test.tsx 验证 API 行为与渲染结果,hooks.test.tsx 单独验证useRow/useItems等 hook 的布局与数据转换逻辑,可作为理解实现细节的补充材料。
主题变量(Design Token)
Descriptions支持通过 CSS-in-JS 主题变量进行定制,官方文档通过<ComponentTokenTable component="Descriptions" />动态渲染其 Token 列表(见 index.zh-CN.md 的「主题变量(Design Token)」小节),样式实现位于 style/index.ts,包含 label 底色、边框颜色、cell padding 等 Token。通过 ConfigProvider 的theme.components.Descriptions即可按项目规范统一调整描述列表的外观。
小结
本文完整覆盖了 Ant DesignDescriptions的两种数据写法、全部 API 参数与默认值、四种典型实战场景(边框、垂直、响应式、自定义样式),并从 index.tsx、useRow.ts、Cell.tsx 等源码出发,讲清了「列数合并 → 数据归一化 → 行布局 → 单元格渲染」的实现链路。无论你是要在详情页快速落地只读信息展示,还是想深入理解 antd 表格类组件的内部设计,本文提供的配置与源码对照都可供直接参考与复用。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考