升级 antd6 建议提前规划好,涉及现有项目 List 组件的重构
- antd List
- pro-components ProList
- List 滚动加载
- 长列表重构
废弃 List 组件是 Ant Design 走向更精简、更专注的架构的一部分,主流观点
- 减少冗余:消除与原生 HTML 和
Table组件的功能重叠。 - 降低复杂度:简化组件库的 API 表面。
- 提升灵活性:鼓励开发者使用更基础的构建块(如
div,Table,Card,Grid)来组合出自己需要的布局,这通常能带来更好、更个性化的结果。
antd6 废弃 List 的考量点
- 与 HTML 标准重复,价值有限:
List组件最基础的功能是渲染一组数据项。- 这个功能完全可以通过原生 HTML 的
<ul>或<ol>结合 CSS 来实现,或者直接使用map函数遍历数组渲染div。 - Ant Design 的
List组件本质上是一个“带样式的div列表”,其核心附加值(样式、分割线、栅格布局)现在被认为不足以 justify 一个独立的组件。
- **功能与更强大的 **
Table组件重叠:- 很多使用
List的场景是渲染一个简单的数据列表。但当需求变得复杂时(例如,需要排序、筛选、固定列等),开发者不得不从List迁移到Table。 Table组件功能极其强大且完善,而List的功能则相对局限。维护两个功能有重叠的组件会增加 API 复杂性和维护成本。
- 很多使用
- 维护成本和 API 一致性:
- 维持一个组件需要持续地处理 Bug、增加新特性、保证 API 的一致性。对于
List这样一个功能相对简单的组件来说,其维护成本与它带来的价值相比,显得不那么划算。 - 移除
List可以简化 Ant Design 的组件库,让团队更专注于增强和维护像Table、Card这样不可替代或功能更复杂的组件。
- 维持一个组件需要持续地处理 Bug、增加新特性、保证 API 的一致性。对于
- 鼓励使用更合适的布局组件:
- 对于复杂的列表布局,特别是需要响应式的栅格布局,
Row/Col组件或Space组件通常是更灵活、更语义化的选择。 - 对于一组相关的卡片式内容,
Card组件组合可能更合适。
- 对于复杂的列表布局,特别是需要响应式的栅格布局,
废弃 List,意味着要自己实现 List 列表,List 原始代码兼容工作要实现。
从长远来看
- List 需求变化太多,CSS Grid, Flex 已经能满足一些基础 List 列表
- 长列表优化,有 react-window,和 @tanstack/react-virtual,需求变化不定,要根据实际业务来匹配技术栈
当前(v5, v6)应该怎么做?
- 不要慌:废弃计划是在 v7,在 v5 和 v6 中你仍然可以继续使用
List组件,会正常工作,只是控制台有警告信息。 - 计划迁移重构:对于新项目,可以开始考虑是否真的需要
List组件,或许上述的替代方案从一开始就是更好的选择。 - 审查现有代码:检查你的项目中所有使用
List组件的地方。评估迁移的代价:- 如果只是简单使用,迁移到原生列表或
Space/Card组合会非常容易。 - 如果你重度使用了
List的grid属性,迁移到Row/Col是最直接的路径。 - 如果你的列表有向复杂表格发展的趋势,直接迁移到
Table组件是长远之计。
- 如果只是简单使用,迁移到原生列表或
- 关注官方公告:密切关注 Ant Design v7 的正式发布公告和迁移指南,届时官方一定会提供更详细的替代方案和代码修改工具(如果可能的话)。
List 替代方案是什么
Listy 组件
官方计划推出新的替代组件叫做 Listy,相关进展可以关注
- List 组件暂时还保留兼容性,但建议迁移到 ProList 或后续的 Listy
- 目前推荐的替代方案是 ProComponents 中的 ProList,在原有 List 基础上扩展了多选、展开等功能,体验更接近 Table,适合后台数据展示场景。
- ProList 文档见:ProList 官方文档
tailwind List 组件
- HTML + tailwindcss@4 重构
- CSS Grid 实现 List,推荐
- CSS Flex 实现 List
- antd 组件代替 List
- 使用 Table 组件
- 使用 Flex 组件代替 List
- 使用 Card 组件组合
- 使用 Row,Col
简单 List
<ul className='border rounded-lg'>
{data.map(item => (
<li
key={item.id}
style={{
padding: '12px 24px',
borderBottom: '1px solid #f0f0f0'
}}
>
{item.content}
</li>
))}
</ul>
Table
<Table
dataSource={data}
columns={[
{
dataIndex: 'content',
// 不设置 title 以隐藏表头
},
]}
pagination={false}
showHeader={false} // 隐藏整个表头
/>
Card
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
{data.map(item => (
<Card key={item.id} size="small">
<p>{item.content}</p>
</Card>
))}
</Space>
Row & Col
<Row gutter={16}>
{data.map(item => (
<Col span={6} key={item.id}>
<div style={{ background: '#fafafa', padding: '16px' }}>
{item.content}
</div>
</Col>
))}
</Row>
Flex
<Flex wrap="wrap" gap="middle">
{data.map(item => (
<div
key={item.id}
style={{
width: '200px',
background: '#fafafa',
padding: '16px'
}}
>
{item.content}
</div>
))}
</Flex>