Ant Design List 竖排列表(itemLayout="vertical")实战指南:从 Demo 到源码级原理
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
本篇指南围绕 Ant Design 中 List 组件的竖排列表样式展开:如何通过itemLayout="vertical"一键切换列表布局,使其从默认的横排紧凑列表变为“主内容 + 右侧封面图 + 底部操作组”的信息流式竖排卡片,并配套分页、头像、元信息(Meta)等完整配置。读完本文,你将掌握竖排列表的完整可运行示例、全部关键参数,以及其在组件源码中的布局实现原理,可直接迁移到后台数据展示、博客信息流、商品列表等真实场景。
一、竖排列表的核心:itemLayout属性
在 Ant Design 的 List 组件中,控制列表项排列方向的是itemLayout属性。官方演示文档 vertical.md 的说明非常直接:将itemLayout设置为vertical即可实现竖排列表样式(Set theitemLayoutproperty toverticalto create a vertical list)。
从源码的类型定义可以看到它的取值被限定为两种:
// components/list/index.tsx export type ListItemLayout = 'horizontal' | 'vertical';默认值为horizontal(见 index.en-US.md 的 API 表格),也就是每个列表项中,标题、描述、操作组在水平方向上排布;而切换为vertical后,列表项呈现为上下结构:主内容区(Meta 信息 + 正文 + 底部操作组)居左、extra附加内容居右,适合承载较长文字、封面图等富内容场景。
二、完整可运行示例:竖排列表 Demo 全解
官方提供了配套的完整示例 vertical.tsx,下面是其核心代码(已保留全部细节,可直接复制运行):
import React from 'react'; import { LikeOutlined, MessageOutlined, StarOutlined } from '@ant-design/icons'; import { Avatar, List, Space } from 'antd'; const data = Array.from({ length: 23 }).map((_, i) => ({ href: 'https://ant.design', title: `ant design part ${i}`, avatar: `https://api.dicebear.com/7.x/miniavs/svg?seed=${i}`, description: 'Ant Design, a design language for background applications, is refined by Ant UED Team.', content: 'We supply a series of design principles, practical patterns and high quality design resources (Sketch and Axure), to help people create their product prototypes beautifully and efficiently.', })); const IconText = ({ icon, text }: { icon: React.FC; text: string }) => ( <Space> {React.createElement(icon)} {text} </Space> ); const App: React.FC = () => ( <List itemLayout="vertical" size="large" pagination={{ onChange: (page) => { console.log(page); }, pageSize: 3, }} dataSource={data} footer={ <div> <b>ant design</b> footer part </div> } renderItem={(item) => ( <List.Item key={item.title} actions={[ <IconText icon={StarOutlined} text="156" key="list-vertical-star-o" />, <IconText icon={LikeOutlined} text="156" key="list-vertical-like-o" />, <IconText icon={MessageOutlined} text="2" key="list-vertical-message" />, ]} extra={ <img width={272} alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png" /> } > <List.Item.Meta avatar={<Avatar src={item.avatar} />} title={<a href={item.href}>{item.title}</a>} description={item.description} /> {item.content} </List.Item> )} /> ); export default App;这个示例集中展示了竖排列表的典型构成要素:
itemLayout="vertical":开启竖排布局;size="large":使用大号尺寸,竖排列表通常搭配大内边距展示;pagination:23 条数据按每页 3 条分页,翻页时通过onChange回调输出当前页码;dataSource+renderItem:声明式数据源渲染,每项渲染为一个List.Item;List.Item.Meta:承载avatar(头像)、title(标题链接)、description(描述)三要素;actions:底部操作组(点赞、收藏、评论数),竖排时自动置于内容下方;extra:右侧附加内容,此处为 272px 宽的封面图,竖排布局下渲染在主内容右侧;footer:列表底部自定义内容。
三、关键参数详解:把竖排列表调成你想要的样子
除了示例中用到的属性,结合 index.zh-CN.md 的 API 文档,竖排列表常用配置如下:
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
itemLayout | 列表项布局,vertical即竖排样式 | horizontal \| vertical | horizontal |
size | 列表尺寸 | default \| large \| small | default |
dataSource | 列表数据源 | any[] | - |
renderItem | 自定义列表项渲染 | (item, index) => ReactNode | - |
rowKey | 自定义每行key的获取方式 | keyof T \| (item: T) => React.Key | "key" |
pagination | 分页配置,false关闭 | boolean \| object | false |
loading | 加载占位 | boolean \| SpinProps | false |
split | 是否展示项间分割线 | boolean | true |
bordered | 是否展示整体边框 | boolean | false |
header/footer | 列表头部 / 底部 | ReactNode | - |
locale | 空数据等文案 | object | { emptyText: '暂无数据' } |
其中pagination还有两个专有配置项(position与align定义在 ListProps 对应的分页合并逻辑中,见下文源码分析):
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
position | 分页显示位置 | top \| bottom \| both | bottom |
align | 分页对齐方式 | start \| center \| end | end |
而List.Item层面,与竖排布局强相关的两个属性是:
extra:附加内容。竖排时渲染在主内容右侧(对应示例中的封面图),横排时渲染在最右侧;文档注释明确说明“通常用在itemLayout为vertical的情况下”。actions:操作组。竖排时显示在内容底部,横排时显示在最右侧。
List.Item.Meta提供avatar、title、description三个插槽,用于快速组织“头像 + 标题 + 描述”的标准信息结构。
四、源码级原理:vertical布局是如何实现的
4.1 布局类名的注入
在 index.tsx 中,组件通过classNames依据itemLayout的值注入布局类名:
// components/list/index.tsx const classString = classNames( prefixCls, { [`${prefixCls}-vertical`]: itemLayout === 'vertical', ... }, );即当itemLayout === 'vertical'时,最外层容器会额外带上ant-list-vertical类。快照测试文件 demo.test.ts.snap 中可以看到竖排 Demo 渲染出的完整类名链:
ant-list ant-list-vertical ant-list-lg ant-list-split ant-list-something-after-last-item依次对应:基础类、竖排布局、size="large"、开启分割线、存在footer/pagination等末尾元素(对应源码中isSomethingAfterLastItem()的判断)。
4.2 列表项的 DOM 结构分支
竖排布局的真正特殊之处在List.Item的渲染逻辑中。在 Item.tsx 中,当itemLayout === 'vertical'且存在extra时,列表项被拆分为“主内容 + 附加内容”两个区块:
// components/list/Item.tsx {itemLayout === 'vertical' && extra ? [ <div className={`${prefixCls}-item-main`} key="content"> {children} {actionsContent} </div>, <div className={`${prefixCls}-item-extra`} key="extra"> {extra} </div>, ] : [children, actionsContent, cloneElement(extra, { key: 'extra' })]}也就是说:
- 竖排 + 有
extra:children(Meta + 正文)与actions(操作组)打包进.ant-list-item-main,extra单独放进.ant-list-item-extra,二者在 Flex 容器中左右排布——这正是示例中“左侧正文、右侧封面图”的来源; - 横排或没有
extra:走另一个分支,children、操作组、extra依次平铺。
4.3 Flex 模式判定:什么时候需要 Flex 容器
同一个文件中,isFlexMode()决定了列表项是否为 Flex 布局:
// components/list/Item.tsx const isFlexMode = () => { if (itemLayout === 'vertical') { return !!extra; } return !isItemContainsTextNodeAndNotSingular(); };- 竖排且提供
extra时进入 Flex 模式(.ant-list-item-main通过flex: 1撑满剩余宽度); - 竖排但没有
extra时退化为普通块级布局,此时extra字段缺省,正文直接垂直堆叠。
这一点有对应的单元测试佐证(Item.test.tsx):
- “vertical itemLayout List should be flex container when there is extra node”——竖排 +
extra时为 Flex 容器; - “vertical itemLayout List should not be flex container when there is not extra node”——竖排但无
extra时不是 Flex 容器。
4.4 分页与数据切片的联动
竖排 Demo 中pagination={{ pageSize: 3 }}的分页行为,在 index.tsx 中可以看到完整调用链:
- 分页状态由组件内部管理:
paginationCurrent默认取defaultCurrent || 1,paginationSize默认取defaultPageSize || 10; paginationProps通过extendsObject合并默认值({ current: 1, total: 0 })、内部状态(total: dataSource.length、当前页、每页条数)与用户传入的配置;- 当前页超出最大页时自动收敛到
largestPage = Math.ceil(total / pageSize); - 渲染前对
dataSource做切片:splice((current - 1) * pageSize, pageSize),只渲染当前页数据; - 翻页事件统一走
triggerPaginationEvent,同时更新内部状态并转发给用户传入的onChange/onShowSizeChange——所以示例中翻页会在控制台打印页码。
此外paginationPosition(position配置,默认bottom)控制分页渲染在列表上方(top)、下方(bottom)还是两处(both),对应源码中paginationContent的两个插入位置。
五、竖排布局的样式与响应式行为
竖排样式的实现集中在 style/index.ts 的genBaseStyle中,几个关键设计值得注意:
- 主内容与附加内容:
.ant-list-item-main设置display: block; flex: 1,保证正文区域占据剩余宽度;.ant-list-item-extra设置marginInlineStart: marginLG,与主内容之间拉开间距。 - Meta 放大:竖排模式下
List.Item.Meta的标题使用fontSizeLG/lineHeightLG(比横排的默认字号更大),并通过metaMarginBottom、titleMarginBottom两个 token 控制与下方内容的间距,让“标题 + 描述”在竖排信息流中更具视觉层级。 - 操作组沉底:
.ant-list-item-action在竖排时设置marginBlockStart与marginInlineStart: auto,配合父级alignItems: 'initial',使点赞、评论等操作组自然落在主内容底部。 - 响应式折叠(
genResponsiveStyle):屏幕宽度 ≤screenMD时调整extra的起始外边距;宽度 ≤screenSM(约 576px)时列表项flexWrap: 'wrap-reverse',extra通过margin: auto auto上移换行——窄屏下封面图会移到正文上方,保证移动端阅读体验。
这些样式 token(如metaMarginBottom、titleMarginBottom、descriptionFontSize、itemPaddingLG等)均通过prepareComponentToken提供默认值,也可以在主题中通过 Component Token 自定义,例如调整竖排列表的标题下间距或描述字号。
六、效果验证:从测试快照看竖排渲染结果
仓库的快照测试对竖排 Demo 的渲染结果有完整记录(demo.test.ts.snap 中的renders components/list/demo/vertical.tsx correctly),核心结构如下:
.ant-list.ant-list-vertical.ant-list-lg.ant-list-split.ant-list-something-after-last-item └─ .ant-spin-nested-loading └─ .ant-list-items ├─ li.ant-list-item │ ├─ .ant-list-item-main │ │ ├─ .ant-list-item-meta(avatar + title + description) │ │ ├─ 正文内容 │ │ └─ ul.ant-list-item-action(Star / Like / Message 三个操作) │ └─ .ant-list-item-extra(封面图) └─ …(其余分页项)可见竖排列表在 DOM 层面严格遵循“主内容 + 附加内容”的左右双栏结构,且每个列表项渲染为li.ant-list-item,操作组以ul > li的无序列表语义输出,兼顾了结构清晰与无障碍可读性。若需进一步自定义,可参考组件提供的语义化配置(classNames/styles支持针对actions、extra模块的定制,自 5.18.0 起可用)。
七、小结
竖排列表(itemLayout="vertical")是 Ant Design List 组件面向富内容场景的重要形态,使用上只需一个属性切换,底层则由 Item.tsx 的“主内容 + 附加内容”双栏结构与 style/index.ts 的专属样式共同支撑,并可无缝叠加pagination分页、size尺寸、loading加载态、footer页脚等能力。结合本文的完整示例、参数表格与源码解读,你可以直接在其基础上构建博客文章流、商品卡片列表、消息中心等后台数据展示页面。
【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考