字节笔记本
2026年3月22日
开源 UI 库中唯一同时实现大表格虚拟化和树表格的 Table 组件
这篇文章将介绍 React Suite(rsuite)的 Table 组件如何同时实现大表格虚拟化和树形表格,这是当时开源 UI 库中唯一支持该组合的 Table 组件。
背景
有这样一个需求,一位 React Suite(以下简称 rsuite)的用户,他需要一个 Table 组件能够像 Jira Portfolio 一样,支持树形数据,同时需要支持大数据渲染。截止到当时为止,开源 UI 库中没有找到可以支持的组件,所以 rsuite 在最新的版本中支持这一特性。
大表格虚拟化
在页面中渲染过多的 DOM 元素会带来性能问题,必须得有一种解决方案去优化它,我们暂且叫做大表格虚拟化。
所谓的大表格虚拟化,其实就是为表格设置一个较大的数据(比如 10000 条数据),然后虚拟一个表格隐藏掉不需要显示的数据。
为了解决让浏览器渲染的大量 DOM 时候出现的性能问题,我们不能把 10000 条数据都渲染到页面,采用一种方式,只渲染可视范围内数据。同时为表格设置一个滚动条,只有在滚动到需要显示的区域时候才渲染该区域的数据,减少的 DOM 数量。
以上是一个 10000 条数据的 Table,渲染后的 HTML 结构中,Table 内只渲染了 14 个 rs-table-row,其中第一个和最后一个是没有 children 的占位符。每一个 rs-table-row 都是绝对定位,所以即使 Table 中删除一个 Row 或者新增一个 Row,也不会改变其他 Row 的位置。在这样的基础上,通过获取滚动条的滚动的位置,就很容易判断当前 Row 的 top 值是否在 Table 的可视范围内,同时更新所有的 Row。
很多优秀的库都实现了这样的功能,原理基本一致,比如 react-virtualized 就提供 Table 组件,但是他不支持 Tree。
树形表格
在表格中展示树形数据的需求很常见,就像甘特图表格展示那样。它有子父层级关系,可以展开子节点。
这样一个表格,很多 Table 组件都支持,但是如果同时需要支持虚拟化就相对比较麻烦,因为在展开关闭节点的时候需要重新计算显示的 DOM 以及设置滚动条的位置。
在 rsuite Table 组件之前的版本中,渲染的树形表格的 DOM 结构是一棵 Tree。所以首先需要把 Tree 拍平,转换一个一维数组,为每一个节点设置父节点,通过父节点的深度渲染 Tree 节点的相对位置。然后就比较好处理,只需要在点击展开关闭节点按钮的时候,处理好数据的过滤。
安装与使用
rsuite 的 Table 组件的设计,对开发还是非常方便,通过 <Table>、<Column>、<Cell>、<HeaderCell> 组件定义结构,通过赋值 data 属性渲染表格数据。
安装
npm install rsuite --save如果你在项目只希望用到 Table,不想安装整个 rsuite 库,你可以单独安装 rsuite-table。
示例代码:
import { Table } from 'rsuite';
const { Column, HeaderCell, Cell } = Table;
const data = [{ id: 1, name: 'foobar', email: 'foobar@xxx.com' }];
ReactDOM.render(
<Table height={400} data={data}>
<Column width={70} align="center" fixed>
<HeaderCell>编号</HeaderCell>
<Cell dataKey="id" />
</Column>
<Column width={200} fixed>
<HeaderCell>姓名</HeaderCell>
<Cell dataKey="name" />
</Column>
<Column width={200}>
<HeaderCell>邮箱</HeaderCell>
<Cell dataKey="email" />
</Column>
</Table>
);更多功能
作为一个成熟的 Table 组件,除了虚拟化和树形表格外,还支持以下功能:
- 自定义调整列宽
- 锁定列
- 自动换行
- 排序
- 分页
- 编辑
- 合并单元格
- 自定义单元格
- 自动列宽
- 可展开行
如果你在项目中需要一个功能丰富的 React Table 组件,rsuite 是一个值得尝试的选择。