Table 表格更新
表格以行和列展示结构化数据,支持排序、选择、列宽调整与无限滚动。
引入
import { Table } from '@heroui/react';用法
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Kate Moore | 首席执行官 | 在职 | kate@acme.com |
| John Smith | 首席技术官 | 在职 | john@acme.com |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
import {Table} from "@heroui/react";
export function Basic() {
return (
<Table>组件结构
引入 Table 组件,并通过点语法访问各部分。
import { Table } from '@heroui/react';
export default () => (
<Table>
<Table.ScrollContainer>
<Table.Content aria-label="Example table">
<Table.Header>
<Table.Column>Name</Table.Column>
<Table.Column>Role</Table.Column>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>Kate Moore</Table.Cell>
<Table.Cell>CEO</Table.Cell>
</Table.Row>
</Table.Body>
</Table.Content>
</Table.ScrollContainer>
<Table.Footer>{/* Optional footer content */}</Table.Footer>
</Table>
);次要变体
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Kate Moore | 首席执行官 | 在职 | kate@acme.com |
| John Smith | 首席技术官 | 在职 | john@acme.com |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
import {Table} from "@heroui/react";
export function SecondaryVariant() {
return (
<Table variant="secondary">排序
在 Table.Column 上设置 allowsSorting 可将列设为可排序。在 Table.Content 上使用 sortDescriptor 与 onSortChange 管理排序状态。
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Emily Davis | 产品经理 | 未激活 | emily@acme.com |
| John Smith | 首席技术官 | 在职 | john@acme.com |
| Kate Moore | 首席执行官 | 在职 | kate@acme.com |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com |
"use client";
import type {SortDescriptor} from "@heroui/react";
import {Table, cn} from "@heroui/react";选择
在 Table.Content 上设置 selectionMode 以启用行选择。全选与每行复选框可使用带 slot="selection" 的 Checkbox。
| 姓名 | 角色 | 状态 | 邮箱 | |
|---|---|---|---|---|
| Kate Moore | 首席执行官 | 在职 | kate@acme.com | |
| John Smith | 首席技术官 | 在职 | john@acme.com | |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com | |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
已选: 无
"use client";
import type {Selection} from "@heroui/react";
import {Checkbox, Table} from "@heroui/react";自定义单元格
| 员工 ID | 成员 | 角色 | 状态 | 操作 | |
|---|---|---|---|---|---|
#1234567 | ED Emily Davisemily@acme.com | 产品经理 | 未激活 | ||
#5273849 | JS John Smithjohn@acme.com | 首席技术官 | 在职 | ||
#4586932 | KM Kate Moorekate@acme.com | 首席执行官 | 在职 | ||
#8293746 | MB Michael Brownmichael@acme.com | 首席财务官 | 在职 | ||
#7492836 | SJ Sara Johnsonsara@acme.com | 首席营销官 | 休假 |
"use client";
import type {Selection, SortDescriptor} from "@heroui/react";
import {Avatar, Button, Checkbox, Chip, Table, cn} from "@heroui/react";可展开行
行可以嵌套以展示层级数据。使用 treeColumn 指定列,并在该列单元格内渲染带 slot="chevron" 的 Button,以便用户展开/收起行。使用 expandedKeys 控制哪些行处于展开状态。
| 姓名 | 类型 | 修改日期 |
|---|---|---|
| 文档 | 文件夹 | 10/20/2025 |
| 项目 | 文件夹 | 8/2/2025 |
| 照片 | 文件夹 | 2/3/2026 |
"use client";
import type {Selection} from "@heroui/react";
import {Button, Table, cn} from "@heroui/react";分页
使用 Table.Footer 在表格下方添加分页组件。
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Kate Moore | 首席执行官 | 在职 | kate@acme.com |
| John Smith | 首席技术官 | 在职 | john@acme.com |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
"use client";
import {Pagination, Table} from "@heroui/react";
import {useMemo, useState} from "react";
列宽调整
使用 Table.ResizableContainer 包裹表格,并在每个可调整宽度的列中加入 Table.ColumnResizer。
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Kate Moore | 首席执行官 | Active | kate@acme.com |
| John Smith | 首席技术官 | Active | john@acme.com |
| Sara Johnson | 首席营销官 | On Leave | sara@acme.com |
| Michael Brown | 首席财务官 | Active | michael@acme.com |
| Emily Davis | 产品经理 | Inactive | emily@acme.com |
import {Chip, Table} from "@heroui/react";
export function ColumnResizing() {
return (
<Table>空状态
在 Table.Body 上使用 renderEmptyState,在表格无数据时展示自定义内容。
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
未找到结果 | |||
"use client";
import {EmptyState, Table} from "@heroui/react";
import {Icon} from "@iconify/react";
异步加载
使用 Table.LoadMore 实现无限滚动:会渲染一行哨兵节点,在进入视口时触发 onLoadMore。
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Kate Moore | 首席执行官 | 在职 | kate@acme.com |
| John Smith | 首席技术官 | 在职 | john@acme.com |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
| Emily Davis | 产品经理 | 未激活 | emily@acme.com |
| Davis Wilson | 首席设计师 | 在职 | davis@acme.com |
"use client";
import {Chip, Spinner, Table} from "@heroui/react";
import {useCallback, useRef, useState} from "react";
虚拟化
Table 通过 Virtualizer 支持虚拟化,仅渲染视口内可见行,从而高效处理大数据集。
"use client";
import {Table, TableLayout, Virtualizer} from "@heroui/react";
interface User {TanStack Table
HeroUI 的 Table 可作为无头表格库之上的渲染层。 本示例使用 TanStack Table 处理列定义、排序与分页,而样式与无障碍由 HeroUI 负责。
| 姓名 | 角色 | 状态 | 邮箱 |
|---|---|---|---|
| Kate Moore | 首席执行官 | 在职 | kate@acme.com |
| John Smith | 首席技术官 | 在职 | john@acme.com |
| Sara Johnson | 首席营销官 | 休假 | sara@acme.com |
| Michael Brown | 首席财务官 | 在职 | michael@acme.com |
"use client";
import type {SortDescriptor} from "@heroui/react";
import type {SortingState} from "@tanstack/react-table";
样式
传入 Tailwind CSS 类
你可以为 Table 的各个部分分别传入类名:
import { Table } from '@heroui/react';
function CustomTable() {
return (
<Table className="border border-purple-200">
<Table.ScrollContainer>
<Table.Content aria-label="Custom styled table">
<Table.Header className="bg-purple-50">
<Table.Column>Name</Table.Column>
</Table.Header>
<Table.Body>
<Table.Row className="hover:bg-purple-50">
<Table.Cell>Kate Moore</Table.Cell>
</Table.Row>
</Table.Body>
</Table.Content>
</Table.ScrollContainer>
</Table>
);
}自定义组件类
若要自定义 Table 组件类,可以使用 @layer components 指令。
了解更多。
@layer components {
.table-root {
@apply relative grid w-full overflow-clip;
}
.table__header {
@apply bg-gray-100;
}
.table__column {
@apply px-4 py-2.5 text-left text-xs font-medium text-gray-600;
}
.table__row {
@apply bg-white border-b border-gray-200;
}
.table__cell {
@apply px-4 py-3 text-sm;
}
.table__footer {
@apply flex items-center px-4 py-2.5;
}
}HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。
CSS 类
Table 组件使用以下 CSS 类(查看源码样式):
基础类
.table-root- 根容器(命名为table-root而非table,因为table是 Tailwind CSS 内置的display: table工具类).table__scroll-container- 横向滚动包裹层与自定义滚动条.table__content-<table>元素.table__header- 表头行(<thead>).table__column- 列表头单元格(<th>).table__body- 表体(<tbody>).table__row- 行(<tr>).table__cell- 数据单元格(<td>).table__footer- 表底容器(位于 table 外部)
进阶类
.table__column-resizer- 列宽拖拽手柄.table__resizable-container- 启用列宽调整的包裹层.table__load-more- 无限滚动的哨兵行.table__load-more-content- 加载指示器的样式容器
变体类
.table-root--primary- 灰色背景容器与卡片式表体(默认).table-root--secondary- 无背景,独立圆角表头
交互状态
Table 同时支持 CSS 伪类与 data 属性,以提供更灵活的状态控制:
- 悬停:
:hover或[data-hovered="true"](行背景变化) - 已选中:
[data-selected="true"](行高亮) - 聚焦:
:focus-visible或[data-focus-visible="true"](行、列与单元格的内嵌焦点环) - 禁用:
:disabled或[aria-disabled="true"](降低透明度) - 可排序:
[data-allows-sorting="true"](列上的交互指针样式) - 拖动中:
[data-dragging="true"](降低透明度) - 放置目标:
[data-drop-target="true"](强调色背景)
API 参考
Table Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
variant | "primary" | "secondary" | "primary" | 视觉变体。Primary 为灰色背景容器;Secondary 为扁平透明行。 |
className | string | - | 根容器的额外 CSS 类。 |
children | React.ReactNode | - | 表格内容(ScrollContainer、Footer 等)。 |
Table.ScrollContainer Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | React.ReactNode | - | Table.Content 元素。 |
Table.Content Props
继承自 React Aria Table。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
aria-label | string | - | 表格的无障碍标签。 |
selectionMode | "none" | "single" | "multiple" | "none" | 选择行为。 |
selectedKeys | Selection | - | 受控的已选中 key。 |
onSelectionChange | (keys: Selection) => void | - | 选择变化时的事件处理函数。 |
sortDescriptor | SortDescriptor | - | 当前排序状态。 |
onSortChange | (descriptor: SortDescriptor) => void | - | 排序变化时的事件处理函数。 |
className | string | - | 额外的 CSS 类。 |
Table.Header Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
columns | T[] | - | 渲染函数模式下的动态列数据。 |
children | React.ReactNode | (column: T) => React.ReactNode | - | 静态列或渲染函数。 |
Table.Column Props
继承自 React Aria Column。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
id | string | - | 列标识符。 |
allowsSorting | boolean | false | 列是否可排序。 |
isRowHeader | boolean | false | 该列是否作为行表头。 |
defaultWidth | string | number | - | 可调整列的默认宽度。 |
minWidth | number | - | 可调整列的最小宽度。 |
children | React.ReactNode | (values: ColumnRenderProps) => React.ReactNode | - | 列内容或带排序方向的渲染函数。 |
Table.Body Props
继承自 React Aria TableBody。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
items | T[] | - | 渲染函数模式下的动态行数据。 |
renderEmptyState | () => React.ReactNode | - | 表格为空时展示的内容。 |
children | React.ReactNode | (item: T) => React.ReactNode | - | 静态行或渲染函数。 |
Table.Row Props
继承自 React Aria Row。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
id | string | number | - | 行标识符。 |
className | string | - | 额外的 CSS 类。 |
children | React.ReactNode | - | 行单元格。 |
Table.Cell Props
继承自 React Aria Cell。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | React.ReactNode | - | 单元格内容。 |
Table.Footer Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | React.ReactNode | - | 表底内容(例如分页)。 |
Table.ColumnResizer Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
Table.ResizableContainer Props
继承自 React Aria ResizableTableContainer。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | React.ReactNode | - | Table.Content 元素。 |
Table.LoadMore Props
继承自 React Aria TableLoadMoreItem。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
isLoading | boolean | false | 数据是否正在加载。 |
onLoadMore | () => void | - | 哨兵行可见时的事件处理函数。 |
children | React.ReactNode | - | 加载指示器内容。 |
Table.LoadMoreContent Props
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 额外的 CSS 类。 |
children | React.ReactNode | - | 加载指示器内容(例如 Spinner)。 |
Table.Collection Props
由 React Aria Collection 重新导出。用于在行内与静态单元格并存时渲染动态单元格(例如复选框)。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
items | T[] | - | 集合条目。 |
children | (item: T) => React.ReactNode | - | 每个条目的渲染函数。 |
TableLayout
| Name | 类型 | 默认值 | 描述 |
|---|---|---|---|
rowHeight | number | undefined | 48 | 行的固定高度(px)。 |
estimatedRowHeight | number | undefined | — | 行高可变时的估算高度。 |
headingHeight | number | undefined | 48 | 分区表头的固定高度(px)。 |
estimatedHeadingHeight | number | undefined | — | 表头高度可变时的估算高度。 |
loaderHeight | number | undefined | 48 | 加载器元素的固定高度(px)。该加载器用于在根级或嵌套行/分区中渲染「加载更多」等加载行。 |
dropIndicatorThickness | number | undefined | 2 | 放置指示器的线条粗细。 |
gap | number | undefined | 0 | 条目之间的间距。 |
padding | number | undefined | 0 | 列表的内边距。 |





