Appearance
React 列排序
点击表头排序图标切换 升序 → 降序 → 取消:列上声明 sortable: true 即显示排序图标;sortMode: 'multiple' 时按住 Shift 点击可叠加多列排序(表头角标显示优先级)。
defaultSort声明初始排序sortMethod自定义比较器(本地化字符串、业务优先级等),返回值由排序方向自动取反- ref 上的
sort()/clearSort()/getSortState()编程式控制,onSortChange监听变化
使用的 API
ts
type Column = {
key: string; // 列标识(必填)
title: string; // 列标题(必填)
width: number; // 列宽(必填)
sortable?: boolean; // 显示排序图标,点击图标排序
defaultSort?: 'asc' | 'desc'; // 初始排序
sortMethod?: (a: Row, b: Row) => number; // 自定义比较器(升序语义)
}
type Options = {
list: T[]; // 数据列表
itemKey: string; // 行唯一标识字段名
estimatedSize: number; // 行预估高度(px)
sortMode?: 'single' | 'multiple'; // 单列 / Shift 多列,默认 single
onSortChange?: (state: SortSpec[]) => void; // 排序变化回调
}
// 实例方法(ref 上调用)
tableRef.current?.sort(colKey, 'asc' | 'desc' | null); // null 取消该列
tableRef.current?.clearSort();
tableRef.current?.getSortState(); // [{ colKey, order }]注意
sortMode 为初始化选项,运行时切换需重建实例——示例里用 key={sortMode} 让 React 重建 VirtTableReact。表格存在合并单元格(spanMethod 产生的合并)时排序会被忽略。
完整语义(三态循环、多列优先级、与合并/筛选的关系)见 Vanilla · 列排序。
示例
微应用尚未挂载。
源码
点击查看源码
tsx
import React from 'react';
import {
VirtTableReact,
type ReactTableColumn,
type VirtTableRef,
type SortSpec,
} from '@virt-table/react';
import { faker } from '@faker-js/faker';
interface Row extends Record<string, unknown> {
id: number;
name: string;
age: number;
score: number;
level: string;
}
const ROW_COUNT = 2000;
const LEVELS = ['S', 'A', 'B', 'C'];
const LEVEL_RANK: Record<string, number> = { S: 0, A: 1, B: 2, C: 3 };
const columns: ReactTableColumn<Row>[] = [
{ key: 'id', title: 'ID', width: 80, sortable: true, defaultSort: 'asc' },
{
key: 'name',
title: '姓名',
width: 180,
sortable: true,
// 自定义比较器:按中文/英文本地化规则比较
sortMethod: (a, b) => a.name.localeCompare(b.name, 'zh-Hans-CN'),
},
{ key: 'age', title: '年龄', width: 100, sortable: true },
{ key: 'score', title: '分数', width: 100, sortable: true },
{
key: 'level',
title: '等级',
width: 100,
sortable: true,
// 自定义比较器:按业务顺序 S > A > B > C,而不是字典序
sortMethod: (a, b) => LEVEL_RANK[a.level]! - LEVEL_RANK[b.level]!,
},
];
const list: Row[] = Array.from({ length: ROW_COUNT }, (_, i) => ({
id: i + 1,
name: faker.person.fullName(),
age: faker.number.int({ min: 18, max: 65 }),
score: faker.number.int({ min: 0, max: 100 }),
level: LEVELS[faker.number.int({ min: 0, max: 3 })]!,
}));
export default function SortTable() {
const tableRef = React.useRef<VirtTableRef>(null);
const [sortMode, setSortMode] = React.useState<'single' | 'multiple'>('multiple');
const [sortState, setSortState] = React.useState<SortSpec[]>([]);
const status = sortState.length
? `当前排序:${sortState.map((s, i) => `${i + 1}. ${s.colKey} ${s.order}`).join(' · ')}`
: '当前排序:无';
return (
<div className="demo-wrapper">
<h3 className="demo-title">React 列排序</h3>
<div className="demo-hint">
点击表头的排序图标切换 <b>升序 → 降序 → 取消</b>;多列模式下按住 <b>Shift</b>{' '}
点击可叠加排序列(表头角标显示优先级)。「姓名」按本地化规则比较,「等级」按 S > A > B > C
业务顺序比较。
</div>
<div className="virt-table-controls">
<label>
排序模式
<select
value={sortMode}
onChange={(e) => setSortMode(e.target.value as 'single' | 'multiple')}
>
<option value="multiple">multiple(多列)</option>
<option value="single">single(单列)</option>
</select>
</label>
<button
type="button"
className="virt-table-btn"
onClick={() => tableRef.current?.sort('score', 'desc')}
>
按分数降序
</button>
<button type="button" className="virt-table-btn" onClick={() => tableRef.current?.clearSort()}>
清除排序
</button>
</div>
<div className="status-text">{status}</div>
<div style={{ width: 660, height: 480 }} className="demo-container">
{/* sortMode 是初始化选项,切换时靠 key 重建表格实例 */}
<VirtTableReact
key={sortMode}
ref={tableRef}
columns={columns}
options={{
list,
itemKey: 'id',
estimatedSize: 40,
buffer: 6,
border: true,
sortMode,
onSortChange: setSortState,
}}
/>
</div>
</div>
);
}