Ant Design Descriptions 组件实战指南:用 items 声明式 API 构建企业级详情页只读信息展示
2026/9/19 0:35:28 网站建设 项目流程

Ant Design Descriptions 组件实战指南:用 items 声明式 API 构建企业级详情页只读信息展示

【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design

Descriptions 是 Ant Design 中用于「成组展示多条只读字段」的经典信息展示组件,最常见的落地场景是订单详情、用户信息、商品规格等详情页(Details Page)。本文以官方文档 components/descriptions/index.en-US.md 为核心骨架,结合仓库内组件源码与真实 Demo,系统讲解 Descriptions 的两种数据声明方式、全部 API 参数、响应式列数/跨度控制、样式定制优先级以及 Design Token 定制方法,读完即可在项目中直接落地一套适配多端屏幕的详情信息面板。

何时使用 Descriptions

官方文档给出的定位非常明确:Commonly displayed on the details page(通常展示在详情页)。当页面需要将一组只读字段(如用户名、电话、地址)以「标签 + 内容」的表格形式整齐排列时,Descriptions 是比手工拼 table 更语义化、更省心的选择。它与 Form 的核心区别在于:Descriptions 不承载交互输入,纯粹用于信息陈列。

两种数据声明方式:items数组与 JSX 子组件

自 5.8.0 起,Descriptions 推荐使用items数组声明数据,而基于<Descriptions.Item>子组件的旧写法在 5.8.0 之后被标记为 deprecated。官方文档给出了两种写法的对照:

// 推荐写法:works when >= 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} />; // 旧写法:works when <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>;

从源码看,两种写法最终会汇合到同一条数据管线:useItems钩子(components/descriptions/hooks/useItems.ts)中优先消费items属性,若未传入则调用transChildren2Items<Descriptions.Item>子节点的propskey转换为等价的对象数组:

const mergedItems = React.useMemo<DescriptionsItemType[]>( () => // Take `items` first or convert `children` into items items || transChildren2Items(children), [items, children], );

因此两者渲染结果完全一致,items只是更利于与后端数据、状态管理直接对接。

Descriptions API 参数详解

官方文档的完整参数表如下(均可在源码 components/descriptions/index.tsx#L31-L51 的DescriptionsProps中找到一一对应的类型定义):

属性说明类型默认值版本
bordered是否显示边框booleanfalse-
colon修改 Descriptions.Item 默认的colon属性值,控制标签后冒号是否显示booleantrue-
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|verticalhorizontal-
size设置列表尺寸,可为middlesmall或不填default|middle|small--
title描述列表的标题,位于顶部ReactNode--

除表格所列属性外,DescriptionsProps还声明了prefixClsclassNamerootClassNamestyleid等通用属性,并支持透传 ConfigProvider 提供的direction(RTL 场景下会自动追加-rtl类名,见 index.tsx#L113)。

值得注意的细节:

  • size:类型为'middle' | 'small' | 'default',若当前组件处于 ConfigProvider 的 size 上下文中且未显式传入,会通过useSize钩子继承全局尺寸(见 index.tsx#L93)。
  • column:支持数字或断点对象两种形式。源码中通过matchScreen(screens, { ...DEFAULT_COLUMN_MAP, ...column }) ?? 3合并计算最终列数(index.tsx#L77-L88),未命中任何断点时兜底为 3 列。官方文档表格中注明 column 的断点对象形式「仅在bordered={true}时生效」。
  • labelStyle/contentStyle(4.10.0 起):通过DescriptionsContext下发给所有 Item 作为「根级」样式,具体优先级见后文「样式定制与覆盖优先级」。

DescriptionItem API 与 span 列宽控制

items数组中的每一项对应以下字段(类型定义见 components/descriptions/Item.ts 与 index.tsx#L23-L29):

属性说明类型默认值版本
contentStyle自定义内容样式CSSProperties-4.9.0
label内容的描述ReactNode--
labelStyle自定义标签样式CSSProperties-4.9.0
span包含的列数number | Screens1screens: 5.9.0

关于 span,官方文档有一段重要补充说明:

The number of span Description.Item. Span={2} takes up the width of two DescriptionItems. When bothstyleandlabelStyle(orcontentStyle) configured, both of them will work. And next one will overwrite first when conflict.

即:span={2}表示该条目占据两个普通条目的宽度;当stylelabelStyle(或contentStyle)同时配置时两者都会生效,发生冲突时后者覆盖前者。这一点与源码 components/descriptions/Cell.tsx#L48-L49 的展开顺序完全一致:labelStyle={{ ...rootLabelStyle, ...labelStyle }}contentStyle={{ ...rootContentStyle, ...contentStyle }}—— Item 级样式始终覆盖根级(Descriptions 级)样式。

span自 5.9.0 起还支持响应式对象(screens: 5.9.0),例如span={{ xl: 2, xxl: 2 }},会在useItems中通过matchScreen依据当前屏幕断点解析为具体数字(useItems.ts#L24-L31)。

布局与视觉定制:bordered / layout / size / colon / title / extra

边框与尺寸

  • bordered={true}:开启表格边框。源码中渲染分支发生变化——bordered 模式下每行使用th(label)+td(content)两个独立单元格,无边框模式下 label 与 content 合并在同一个td内通过 flex 布局排布(见 components/descriptions/Row.tsx#L128-L137)。
  • size="middle" | "small":控制单元格内边距。从 components/descriptions/style/index.ts 的样式生成逻辑看,middle 使用paddingSM、small 使用paddingXS,实现紧凑型详情面板。

布局方向

  • layout="horizontal"(默认):标签与内容同行排列。
  • layout="vertical":标签与内容上下堆叠。源码中 vertical 模式下每个逻辑行会被拆成两行<tr>渲染:第一行只渲染 label(th),第二行只渲染 content(td),见 Row.tsx#L105-L126。
// 来自 demo/vertical.tsx:地址占两列宽度,其余条目单列 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: 'Address', span: 2, children: 'No. 18, Wantang Road, Xihu District, Hangzhou, Zhejiang, China' }, { key: '5', label: 'Remark', children: 'empty' }, ]; <Descriptions title="User Info" layout="vertical" items={items} />;

冒号、标题与操作区

  • colon={false}:隐藏标签后的冒号。样式层通过在 label 元素上追加-item-no-colon类并把::after伪元素内容置空实现(style/index.ts#L182-L184)。
  • title:面板顶部标题,样式上使用fontWeightStrong加粗、fontSizeLG放大(style/index.ts#L131-L138)。
  • extra:右上角操作区(如「编辑」「更多」按钮),通过marginInlineStart: 'auto'推到标题右侧(style/index.ts#L139-L143)。
<Descriptions title="User Info" extra={<Button size="small" type="link">Edit</Button>} items={items} />

响应式列数与响应式 span

Descriptions 内置了一套断点默认列数映射,定义在 components/descriptions/constant.ts:

const DEFAULT_COLUMN_MAP: Record<Breakpoint, number> = { xxl: 3, xl: 3, lg: 3, md: 3, sm: 2, xs: 1, };

即默认在手机屏(xs)上每行 1 列、平板(sm)2 列、桌面端(md 及以上)3 列。开发者可通过column传入断点对象覆盖任意断点的列数,配合useBreakpoint(grid/hooks/useBreakpoint)实时响应窗口变化。

官方 responsive Demo 给出了完整的多断点实践:column={{ xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }}让宽屏下每行容纳 4 列;同时条目级span也可以按断点自适应,例如「Config Info」「Hardware Info」两项在窄屏占 1 列、中等屏占 2~3 列、超宽屏占 2 列:

{ 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 </> ), }

样式定制与覆盖优先级

  • Descriptions 级labelStyle/contentStyle(4.10.0)作为根级样式通过DescriptionsContext下发(DescriptionsContext.ts)。
  • Item 级labelStyle/contentStyle(4.9.0)作用在单个条目上。
  • 单元格级style作用在整格(td/th)上。

合并顺序在 Cell.tsx#L48-L49 中体现为{ ...root, ...item },因此条目级覆盖根级;文档同时强调stylelabelStyle/contentStyle并行生效、冲突时后者(labelStyle/contentStyle)覆盖前者。仓库中的 style Demo 与 padding Demo 展示了具体效果。

源码级原理剖析:从items到表格行的渲染链路

理解 Descriptions 的底层渲染流程,有助于排查 span 越界、列数不符等布局问题。整条链路可概括为四步:

  1. 列数解析(index.tsx#L77-L88):mergedColumn合并默认断点映射与用户column,得到当前屏幕下的实际列数。
  2. 条目归一(useItems.ts):把items或 children 统一成内部条目数组,并将响应式span对象解析为数字。
  3. 行计算(useRow.ts):getCalcRows按列数把条目切分为多个行数组,逐项累计剩余列数rowRestCol;当某条span超出本行剩余列数时,会将该条目的 span 自动收缩为剩余列数并标记exceed,在开发模式下通过devUseWarning输出告警:Sum of column span in a line not match column of Descriptions.。这一机制保证任何 span 配置都不会破坏表格结构。
  4. 单元格渲染(Row.tsx + Cell.tsx):非 bordered 模式每个条目渲染为单个td(内部用 flex 容器排列 label 与 content,并通过colSpan={span}扩展宽度);bordered 模式拆分为th+td两个单元格,content 的colSpanspan * 2 - 1;vertical 模式再进一步拆成 label 行与 content 行两行<tr>

最终 DOM 结构稳定为div.descriptions > div.descriptions-header + div.descriptions-view > table > tbody > tr.descriptions-row,官方测试用例(components/descriptions/tests/index.test.tsx、hooks.test.tsx)对上述行计算与响应式逻辑均有覆盖验证。

Design Token 定制

Descriptions 支持通过主题 Token 统一定制视觉风格,组件的ComponentToken定义于 components/descriptions/style/index.ts#L9-L56,官方文档以<ComponentTokenTable component="Descriptions" />动态渲染完整 Token 表格,源码中可确认的 Token 包括:

Token说明默认值(由prepareComponentToken派生)
labelBg标签背景色(bordered 模式)colorFillAlter
titleColor标题文字颜色colorText
titleMarginBottom标题下间距fontSizeSM * lineHeightSM
itemPaddingBottom子项下内边距padding
itemPaddingEnd子项结束(右侧)内边距padding
colonMarginRight冒号右间距marginXS
colonMarginLeft冒号左间距marginXXS / 2
contentColor内容文字颜色colorText
extraColor额外区域文字颜色colorText

例如在 ConfigProvider 中定制标签背景色与标题颜色:

<ConfigProvider theme={{ components: { Descriptions: { labelBg: '#f5f5f5', titleColor: '#1677ff', contentColor: 'rgba(0, 0, 0, 0.88)', }, }, }} > <Descriptions title="User Info" bordered items={items} /> </ConfigProvider>

典型场景速查

仓库 demo 目录 提供了覆盖各场景的完整可运行示例,可对照查阅:

  • basic.tsx:最基础的items用法,搭配title展示用户信息;
  • border.tsx:bordered表格样式 + 多条目span组合,典型订单/账单详情;
  • responsive.tsx:响应式column与响应式span结合的多端适配方案;
  • vertical.tsx:layout="vertical"上下堆叠布局;
  • size.tsx、padding.tsx:尺寸与内边距调节;
  • style.tsx:labelStyle/contentStyle 自定义;
  • jsx.tsx:旧版<Descriptions.Item>JSX 写法对照;
  • component-token.tsx:Component Token 定制效果。

小结

Descriptions 的核心价值在于用极少的配置把「一组只读字段」编排成结构清晰、天然响应式的信息表格。掌握要点即可应对绝大多数详情页需求:优先使用items数组声明数据(5.8.0+);用数字或断点对象控制column与条目span实现多端自适应;借助labelStyle/contentStyle与 Design Token 完成视觉定制;理解useRow的列数兜底与开发期告警,可快速定位布局异常。如需更完整的参数说明,可直接查阅官方文档 components/descriptions/index.en-US.md 及中文版 index.zh-CN.md。

【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询