@canvas-components/react-list-table
@canvas-components/react-list-table 是 @canvas-components/list-table 的 React 适配层,负责把原生 Canvas 表格接入 React 应用,并提供更接近业务开发习惯的组件化入口。
通过顶层 loading 属性控制数据加载状态:<ReactListTable loading={loading} dataSource={rows} columns={columns} />。加载期间展示加载提示并保留汇总标题;加载完成后,组件自动计算并统一展示完整汇总结果。服务端汇总可通过 query.summaryValues 提供,业务侧无需单独管理汇总计算状态。
通过 ref 读取数据
const tableRef = useRef<ReactListTableRef<Row>>(null);
<ReactListTable ref={tableRef} columns={columns} dataSource={rows} />;
// 获取当前原始数据,包含表格内编辑后的记录。
const allRows = tableRef.current?.getDataSource() ?? [];
// 获取过滤后的完整结果,保留当前排序,不受分页、滚动窗口或分组折叠影响。
const filteredRows = tableRef.current?.getFilteredData() ?? [];
从 react 导入 useRef,从本包导入 ReactListTable 和 ReactListTableRef;Row 为业务行类型。两个方法均返回数组浅拷贝,行对象仍与表格共享,请勿直接修改记录。未建立原生实例时返回空数组。异步过滤或排序期间,getFilteredData() 返回最近已完成的异步查询结果;尚无此结果时回退当前原始数据。需读取新结果时,请等待 onChange 通知。远程查询模式只返回宿主当前传入的 dataSource,不会获取服务端全部记录。原生 ListTable 实例也提供同名方法。
自定义条件格式
可在列配置的 conditionalFormats 中传入默认规则。规则按数组顺序匹配当前列的原始值,首条命中规则设置该单元格的背景色和文字颜色;例如:
import { ReactListTable } from "@canvas-components/react-list-table";
const columns = [
{
key: "score",
dataIndex: "score",
title: "分数",
conditionalFormats: [
{
id: "low-score",
name: "低分",
operator: "lt",
value: 60,
backgroundColor: "#ffccc7",
textColor: "#a8071a",
},
{
id: "high-score",
name: "高分",
operator: "gte",
value: 90,
backgroundColor: "#d9f7be",
textColor: "#237804",
},
],
},
];
const rows = [
{ id: 1, score: 55 },
{ id: 2, score: 95 },
];
<ReactListTable columns={columns} dataSource={rows} rowKey="id" />;
规则的 scope 可设为 "cell"(默认)或 "row"。row 会将该规则样式应用到整条命中数据行;完整规则说明见 @canvas-components/list-table 文档中的“按列条件格式”。支持 eq、neq、gt、gte、lt、lte、between、contains、empty 和 notEmpty。
右键调试开关
右键菜单按当前状态显示“开启调试”或“关闭调试”,仅切换当前表格的调试辅助显示和命中信息;保留 debug 中明确配置的细项与性能回调,不触发查询、不写入本地缓存。普通重渲染保留手动开关状态,外部调试字段实际变更或切换 storageKey 时同步。可用 contextMenu.disabledFeatures: ["debug"] 隐藏此入口。
右键分页配置
表头或表体右键菜单中的“分页配置”可编辑启用状态、当前页、每页条数、尺寸、文案模板、快速跳页与高级参数。pagination={false} 表示初始关闭,用户仍可从弹窗开启。关闭后隐藏分页控件并展示全部已加载数据;远程查询是否返回全部记录由业务处理。
<ReactListTable
columns={columns}
dataSource={rows}
pagination={false}
onPaginationConfigChange={(value) => console.log("分页配置已更新", value)}
/>;
// 也可通过原生实例或 React ref 读取/应用配置。
const snapshot = tableRef.current?.getPaginationConfig();
tableRef.current?.setPaginationConfig({
pageSize: 20,
current: 1,
size: "small",
pageInfoFormat: "第 {current} 页 / 共 {totalPages} 页",
totalFormat: "第 {start}–{end} 条,共 {total} 条",
});
size 支持 auto(默认跟随表格)、small、middle、large。pageInfoFormat 支持 {current}、{totalPages},totalFormat 支持 {total}、{start}、{end};模板仅作为文本,不支持 HTML 或表达式。totalFormat=false 隐藏统计,未传时沿用原 showTotal。简洁模式保留中间“当前页 / 总页数”,隐藏左侧条数统计和额外页码信息。
弹窗修改只影响草稿和预览,确定才生效,取消不修改表格。总条数和总页数只读。mode="scroll" 保留滚动加载行为,弹窗仅开放开关与每批条数,不提供模式切换。
配置由核心内部管理,通知不要求业务回写。普通父组件重渲染、内容相同的新对象、只更新事件函数,都不会撤销用户配置;外部参数实际改变时按字段同步。total 和回调持续使用最新输入;storageKey 切换重新初始化。pagination 一直为 false 时,重复传 false 不会撤销用户内部开启;外部对象实际切换成 false 时则关闭。
数据参数变化继续触发现有 onChange/query.onChange;关闭时查询分页值为 false,显示项变化不触发查询。可在弹窗勾选“缓存到本地”,选择“当前表格”(需要稳定 storageKey)或“所有表格”。单表缓存优先于共享默认;共享默认跳过外部明确传入 pagination={false} 的表格。当前页、业务 total、函数和加载模式不缓存,cachePageSize=false 仍禁止读写条数。没有整份配置缓存时,初始化条数沿用显式 pageSize、已有条数缓存、默认 10 的顺序。可通过 contextMenu.disabledFeatures: ["pagination"] 隐藏入口。
属性更新与性能
- 相同属性引用的父组件重渲染由
React.memo跳过;组件内部交互仍正常更新。 onChange以及查询、分页、行选择、展开、拖拽和性能通知等事件使用稳定入口,调用时读取最近一次已提交的回调,避免仅回调引用变化就重置底层查询。scroll、theme、pagination等常用配置进行第一层字段比较,内容相同的新对象复用之前的配置。嵌套对象和数组仍按引用判断。columns、dataSource、受控选中/展开数组,以及rowKey、onRow、列渲染、getCheckboxProps等影响数据或展示的函数,变化时继续刷新。大数据数组不做深比较,建议用useMemo或稳定状态保存,并在内容改变时更新引用。
示例效果

完整示例图集
100w 数据渲染

行选择

单元格内容

斑马条纹

主题切换

高亮模式

右键菜单

数据格式

省略提示

可展开行

单元格编辑

远程查询

表格分页

空状态

宽高配置

表头排序、过滤、固定

多级表头

汇总行

合并行列

拖动改变列宽

轮播滚动

缓存配置

拖拽表头排序

跨表行拖拽

超级示例

功能作用
- 提供
ReactListTable组件 - 内置工具栏、分页层、编辑层、tooltip、图片预览
- 暴露
ref方法,方便外部校验和滚动定位 - 保持底层大数据性能和纯原生渲染能力
手动输入每页条数
按钮分页模式开启 pagination.showSizeChanger 后,每页条数下拉框默认允许手动输入:
<ReactListTable
columns={columns}
dataSource={dataSource}
storageKey="orders-table"
pagination={{
showSizeChanger: true,
cachePageSize: true,
pageSizeOptions: [10, 20, 50, 100],
minPageSize: 5,
maxPageSize: 500,
}}
/>
输入正整数后按回车或失焦生效,切回第 1 页,输入的值会保留为当前分页器的下拉候选项。上下限包含边界,默认最小 1、最大 Number.MAX_SAFE_INTEGER;非法或越界输入不触发变更。可设置 pagination.allowPageSizeInput: false 关闭手动输入。滚动加载模式不显示分页器。
自定义候选项支持删除;删除当前选中的自定义项时回到默认每页 10 条并切回第 1 页(回退值遵守上下限)。storageKey 配合 pagination.cachePageSize: true 缓存用户选中的分页尺寸,重新打开后恢复,删除当前项后的回退值也会缓存。未传开关时兼容已有缓存行为,设置 false 禁止读取和写入缓存。显式传入 pagination.pageSize 时以受控值为准,远程请求场景可先调用 getListTableStoredPageSize(storageKey, pagination) 初始化请求条数。
安装方法
pnpm add @canvas-components/react-list-table @canvas-components/list-table react@^16.8 react-dom@^16.8
最低依赖版本:
react >= 16.8.0react-dom >= 16.8.0Node.js >= 18.12.0pnpm >= 9.0.0
使用方法
打印配置可以通过 printPresets 预设交给 ReactListTable。每个预设有一个用于选择的名称和打印配置;未提供的字段使用默认值。没有已保存配置时默认使用第一个预设,也可以在打印配置弹窗中切换;启用本地缓存后,后续打开优先恢复所选预设和本地修改。
import {
ReactListTable,
type ReactListTablePrintPreset,
} from "@canvas-components/react-list-table";
const printPresets: ReactListTablePrintPreset[] = [
{
name: "横向明细",
config: {
title: "明细清单",
paperSize: "a4",
orientation: "landscape",
rowsPerPage: 24,
pageMargins: { top: 10, right: 10, bottom: 10, left: 10 },
columns: [
{ key: "name", width: 60, align: "left" },
{ key: "amount", width: 35, align: "right" },
],
selectedKeys: ["name", "amount"],
},
},
];
<ReactListTable
storageKey="invoice-list"
printPresets={printPresets}
columns={columns}
dataSource={data}
/>;
配置名称显示在打印配置弹窗顶部。列通过 key 对应表格列;列宽单位为毫米。需要缓存预设选择和用户调整时提供 storageKey 并保持弹窗中的本地缓存选项开启。
右键直接打印(包括选择模板打印)会先显示“每次打印页数”设置,默认每批 50 页。可通过 directPrintPagesPerBatch={20} 修改默认值,用户仍可在开始前调整。每批只生成并加载指定数量的实际打印页(包括自动续页),关闭浏览器打印窗口后释放该批 iframe;点击“继续下一批”才生成后续批次,也可以取消剩余任务。浏览器无法区分打印窗口中的“打印”和“取消”,因此批次之间不会自动继续。
默认打印设计集成
ReactListTable 默认启用官方打印设计集成,右键菜单提供直接打印和打印设计。每张表使用自己的打印数据、预设和 storageKey,无需在应用根部注册 Provider,也无需单独导入打印样式。
如需替换官方集成,可在应用根部注册自定义集成,该范围内的表格共用组件和工具入口:
import {
ReactListTablePrintProvider,
defineReactListTablePrintIntegration,
} from "@canvas-components/react-list-table";
import { builtinListTablePrintIntegration } from "@canvas-components/print-design-plugin/list-table-print";
const integration = defineReactListTablePrintIntegration(
builtinListTablePrintIntegration,
);
<ReactListTablePrintProvider integration={integration}>
<App />
</ReactListTablePrintProvider>;
接入自定义组件时,以 builtinListTablePrintIntegration 为基础替换原生注册表和 React 创建器,再调用 defineReactListTablePrintIntegration 校验;右键设计器和直接打印会使用这一份集成。集成项还必须提供 Host、菜单和模板能力,可复用官方宿主实现,也可自行实现。向 Provider 传入 null 可停用该范围内的打印设计入口,表格实例自定义的 onPrint 仍可使用。
import { useMemo, useRef } from "react";
import {
ReactListTable,
type ReactListTableRef,
} from "@canvas-components/react-list-table";
interface UserRow {
id: number;
name: string;
age: number;
}
export function DemoTable() {
const tableRef = useRef<ReactListTableRef<UserRow> | null>(null);
const columns = useMemo(
() => [
{ key: "name", title: "姓名", dataIndex: "name", width: 180 },
{
key: "age",
title: "年龄",
dataIndex: "age",
width: 120,
align: "right" as const,
},
],
[],
);
return (
<ReactListTable<UserRow>
ref={tableRef}
rowKey="id"
height={480}
columns={columns}
dataSource={[
{ id: 1, name: "张三", age: 28 },
{ id: 2, name: "李四", age: 31 },
]}
toolbar={{ showRefresh: true, showExport: true }}
/>
);
}
属性说明
ReactListTableProps
ReactListTableProps 继承自 ListTableOptions,并额外补充 React 宿主相关能力。
| 属性 | 类型 | 说明 |
|---|---|---|
width | number | string | 表格宽度 |
height | number | string | 表格高度 |
emptyText | string | 空状态文案 |
scroll | ReactListTableScrollConfig | React 风格滚动尺寸配置 |
locale | ReactListTableLocale | 本地化文案 |
onChange | ListTableQueryChange<RecordType> | 查询状态变更回调 |
className | string | 根节点类名 |
style | CSSProperties | 根节点样式 |
title | ReactNode | 标题栏左侧内容 |
toolbar | false | ReactListTableToolbarOptions | 工具栏配置,传 false 隐藏 |
其余如 columns、dataSource、rowSelection、expandable、pagination、rowDrag、draggable、resizable 等属性与 @canvas-components/list-table 保持一致。
ReactListTableToolbarOptions
| 属性 | 类型 | 说明 |
|---|---|---|
showRefresh | boolean | 是否显示刷新按钮 |
showFullscreen | boolean | 是否显示全屏按钮 |
showDensity | boolean | 是否显示密度切换 |
showColumnSetting | boolean | 是否显示列设置 |
columnSettingWidth | number | string | 列设置面板宽度 |
columnSettingHeaderExtra | ReactNode | 列设置标题区中重置按钮前的扩展内容 |
showExport | boolean | 是否显示导出按钮 |
exportOptions | ListTableExportXlsxOptions | 默认导出的文件名和汇总行配置 |
onRefresh | () => void | 点击刷新回调 |
onExport | () => void | 自定义导出回调 |
getFullscreenNode | () => HTMLElement | null | 自定义全屏节点 |
extra | ReactNode | 工具栏右侧额外内容 |
统一切换调试模式
ReactListTableDebugProvider 可为后代中的全部 ReactListTable 同步开启核心调试模式,并默认显示表头、表体、固定列分割线、命中区域和表头操作区。表格自身通过 debug 传入的其他选项仍会保留,也可以显式关闭某个可视化项:
import {
ReactListTable,
ReactListTableDebugProvider,
} from "@canvas-components/react-list-table";
<ReactListTableDebugProvider enabled={statsEnabled}>
<ReactListTable
columns={columns}
dataSource={dataSource}
debug={{ showBodyBounds: true }}
/>
</ReactListTableDebugProvider>;
方法说明
ReactListTableRef
| 方法 | 签名 | 说明 |
|---|---|---|
validate | () => Promise<RecordType[]> | 触发表格校验 |
exportXlsx | (options?: ListTableExportXlsxOptions) => void | 导出 XLSX,可配置文件名和汇总行 |
scrollTo | (options) => void | 滚动到指定行 |
getDebugSnapshot | () => ListTableDebugSnapshot | null | 获取调试快照 |
导出文件名弹窗使用 react-components 的 ReactModal、ReactInput,默认开启,文件后缀不可编辑。通过表格 exportOptions={{ fileName: "报表", promptFileName: false }} 可配置默认名称并跳过弹窗;工具栏 toolbar.exportOptions 或实例 exportXlsx 的同名选项可覆盖默认配置。取消不会生成文件。XLSX 默认追加当前已显示的汇总行,传入 includeSummary: false 可关闭。
类型别名
| 类型 | 说明 |
|---|---|
ReactListTableTableProps<RecordType> | ReactListTableProps<RecordType> 的别名 |
ReactListTableColumnType<RecordType> | 单列类型别名 |
ReactListTableColumnsType<RecordType> | 列数组类型别名 |
ReactListTableRowSelection<RecordType> | 行选择类型别名 |
ReactListTablePagination | 分页类型别名 |
ReactListTableQuery<RecordType> | 查询类型别名 |
推荐场景
- React 后台管理表格
- 大数据量只读 / 可编辑表格
- 需要原生性能但又希望保留 React 组件用法的场景
清空行选择
通过组件 ref 调用 tableRef.current?.clearRowSelection()。该方法清空通过选中 key 设置的行高亮、行勾选和 Shift 选择锚点,配置 rowSelection 且选择发生变化时触发 rowSelection.onChange([], [], { type: "none" })。受控模式请在回调中同步 selectedRowKeys。
过滤面板勾选或取消过滤项并即时应用时,会立即清空全部已选行,不保留仍在过滤结果中的勾选。
调用 tableRef.current?.setSelectedRowKeys(["1", "2", "3"]) 可以主动设置行高亮,无需配置 rowSelection,也不会新增 checkbox / radio 列。配置 rowSelection 时同时同步勾选并触发 onChange;单选模式只保留第一个 key。传入空数组等同清空,普通配置更新会保留未受控的选中 key。
onRow(record, rowIndex) 可返回 style: { backgroundColor, color } 实现受控业务高亮;建议用 useCallback 维护依赖,业务选中变化时会刷新 Canvas。业务权限与动态条件使用 hidden(不缓存),用户列设置使用 visible(默认 true,按 storageKey 缓存)。实际显示为 hidden !== true && visible !== false;业务条件恢复时保留原用户偏好。详见 业务显隐与用户列偏好。
禁用的原生按钮内容(type: "button", disabled: true)不会触发内容、单元格、行或列的点击回调,也不会改变活动单元格和鼠标选区;同一单元格内其他启用按钮仍可独立交互。
共享设置变更同步适用的已挂载表格及其他标签页;单表覆盖不受影响。取消缓存删除所选范围的记录,当前运行时配置保留;重新挂载时按单表、共享、外部输入回退。也可调用 setPaginationConfig(value, { enabled: true, scope: "table" | "all" }) 保存配置。