数据展示有已知边界
NnTable 表格
排序、筛选、分页和固定列。
示例
API
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
columns | TableColumn[] | [] | 列定义,结构见下文。 |
dataSource | Record<string, unknown>[] | [] | 表格数据。 |
pagination | boolean | TablePagination | — | false 关闭分页;true、未传或传对象时,只要总行数大于 0 就显示分页。默认每页 10 条。 |
loading | boolean | { spinning?: boolean } | false | 显示加载遮罩。对象形式只读取 spinning。 |
scroll | { x?: number | string | boolean; y?: number | string } | {} | 横向最小宽度与纵向最大高度。x: true/max-content 使用 min-width: max-content。 |
rowKey | string | ((record, index) => PropertyKey) | 'key' | 行键;字符串字段缺失时继续回退到 record.key 和索引。 |
rowClassName | string | ((record, index) => unknown) | '' | 行 class。 |
customRow | (record, index) => object | — | 返回对象会 v-bind 到 <tr>,可包含原生属性和事件监听器。 |
size | string | 'middle' | small 使用紧凑样式,其他值为默认样式。 |
bordered | boolean | false | 显示表格边框。 |
TableColumn
ts
interface TableColumn {
key?: PropertyKey;
dataIndex?: string | PropertyKey[]; // 字符串支持 a.b.c 路径
title?: unknown | (() => unknown);
width?: number | string;
align?: string;
ellipsis?: boolean;
fixed?: true | 'left' | 'right';
sorter?: boolean | ((left: Record<string, unknown>, right: Record<string, unknown>) => number);
sortDirections?: Array<'ascend' | 'descend' | null>;
filters?: Array<{ text: unknown; value: unknown }>;
onFilter?: (value: unknown, record: Record<string, unknown>) => boolean;
customRender?: (context: TableCellContext) => unknown | { children: unknown };
children?: TableColumn[];
}
interface TableCellContext {
text: unknown;
value: unknown; // 与 text 相同
record: Record<string, unknown>;
index: number; // 当前 displayedRows 中的索引
column: TableColumn;
}title和customRender可返回 Vue 可渲染内容;customRender返回普通{ children }时只渲染其children。dataIndex可以是键数组或点分隔字符串。没有customRender/bodyCell时,数组以,连接,对象使用JSON.stringify。sorter为函数时在当前dataSource上执行客户端排序。其他真值只改变排序状态并触发change,适合由父组件处理。filters显示多选筛选菜单;只有同时提供onFilter才会执行客户端过滤。fixed使用 CSS sticky。多个固定列的偏移只会累加可转为数字的width。
TablePagination
ts
interface TablePagination {
current?: number;
pageSize?: number;
total?: number;
showSizeChanger?: boolean;
pageSizeOptions?: Array<number | string>; // 默认 10、20、50、100
showQuickJumper?: boolean; // 默认显示,显式 false 才隐藏
position?: string[]; // 包含 bottomCenter 时居中
showTotal?: (total: number, range: [number, number]) => unknown;
onChange?: (current: number, pageSize: number) => void;
onShowSizeChange?: (current: number, pageSize: number) => void;
}当有限数字 total 大于当前处理后的行数时,组件视为远程分页,不再切片 dataSource。传入 current 或 pageSize 后属于受控值,父组件应在回调或 change 后更新配置。
Events
| 事件 | 参数 | 说明 |
|---|---|---|
change | (pagination, filters, sorter, extra) | 分页、页大小、排序或筛选确认后触发。 |
事件对象结构:
ts
interface TableChangePagination {
current: number;
pageSize: number;
total: number;
}
type TableChangeFilters = Record<string, unknown[]>; // 键为 column.key/dataIndex/生成键
interface TableChangeSorter {
column?: TableColumn;
columnKey?: string;
field?: TableColumn['dataIndex'];
order?: 'ascend' | 'descend' | null;
}
interface TableChangeExtra {
currentDataSource: Record<string, unknown>[]; // 过滤、排序后的全部当前数据,不是当前页切片
}没有有效排序时 sorter 是空对象。
Slots
| 名称 | 作用域参数 | 说明 |
|---|---|---|
bodyCell | { column, record, index, text, value } | 每个单元格都会调用。返回至少一个有意义节点时优先于 column.customRender 和原始值。 |
emptyText | — | 替换空表格中的默认 NnEmpty。 |
当前限制
children只展开一层为普通叶列,不渲染分组表头;更深层 children 不会继续展开。- 没有列级命名插槽、行选择、展开行、合并单元格或受控 sorter/filter 状态。
- 默认分页是开启的;需要完整展示全部数据时必须显式传
:pagination="false"。 - 远程模式只避免分页切片;若仍传入函数
sorter或onFilter,当前页数据仍会在客户端处理。
