antd6的table排序功能
- 技术栈:react 19 / ts / react-query
- 效果:升序->降序->去掉排序->升序一直循环
- 如果不需要接口,可跳到实现
父组件
- 请求参数 :
- sort_by :排序字段(created_at/updated_at)
- order_by :排序方向(asc/desc,默认asc)
接口实现
js
复制代码
// src\api\test.ts
import type { SortField } from "@/types/device";
import { apiClient } from "./http"; // 只是axios请求
import { useQuery } from "@tanstack/react-query";
export interface Response {
list: []
page: number
size: number
total: number
}
export interface Params {
page?: number;
pageSize?: number;
sort_by?: SortField | '';
order_by?: 'asc' | 'desc' | '';
}
export const useGetList = (params: Params) => {
return useQuery<Response>({
queryKey: ['useGetList', params],
queryFn: async () => {
const { data: response } = await apiClient.get('/test', { params: params })
return response.data
},
})
}
定义类型
js
复制代码
// src\types\test.ts
// 可排序字段
export const SORTABLE_FIELDS = [
'created_at',
'updated_at',
] as const;
export type SortField = typeof SORTABLE_FIELDS[number];
export type SortOrderBE = 'asc' | 'desc' | undefined;
export type SortOrderUI = 'ascend' | 'descend';
父组件
tsx
复制代码
// src\views\test\index.tsx
import React, { useState } from 'react';
import { useGetList, type Device, type useGetDeviceListParams, } from '@/api/test';
import type { SortField } from '@/types/test';
import DeviceTable from './components/DeviceTable';
const INIT_VALUES = { page: 1, pageSize: 10 };
const DeviceManagement: React.FC = () => {
const [params, setParams] = useState({ ...INIT_VALUES });
// ⭐这里是重点
// 排序处理
const handleSortChange = (sortBy?: SortField | '', orderBy?: 'asc' | 'desc' | '') => {
setParams((prev) => ({
...prev,
sort_by: sortBy ?? '',
order_by: orderBy ?? '',
}));
};
return (
<>
<DeviceTable
// 多余的配置参数省略,也就是一些配置page/data之类
sortBy={params.sort_by}
orderBy={params.order_by}
onSortChange={handleSortChange}
/>
</>
);
};
export default DeviceManagement;
子组件
js
复制代码
import React from 'react';
import { Table, type TableProps } from 'antd';
import type { Device } from '@/api/device';
import { type SortField, type SortOrderBE, type SortOrderUI } from '@/types/test';
interface DeviceTableProps {
sortBy?: SortField | '';
orderBy?: SortOrderBE | ''; // 改为后端类型,允许空字符串
onSortChange?: (sortBy: SortField | '', orderBy: SortOrderBE | '') => void;
}
// ⭐这里是重点
/* ---------- 工具 ---------- */
const toUIOrder = (be?: SortOrderBE | ''): SortOrderUI | undefined =>{
return be === 'asc' ? 'ascend' : be === 'desc' ? 'descend' : undefined;
}
/**
* 设备表格组件
* 展示设备列表数据并提供分页和编辑功能
*/
const DeviceTable: React.FC<DeviceTableProps> = ({
sortBy,
orderBy,
onSortChange,
}) => {
// 表格列配置
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 100,
},
{
title: '创建时间',
dataIndex: 'created_at',
key: 'created_at',
width: 170,
sorter: true,
sortOrder: sortBy === 'created_at' ? toUIOrder(orderBy) : null,
},
{
title: '更新时间',
dataIndex: 'updated_at',
key: 'updated_at',
width: 170,
sorter: true,
sortOrder: sortBy === 'updated_at' ? toUIOrder(orderBy) : null,
},
];
// ⭐这里是重点
const handleTableChange: TableProps<Device>['onChange'] = (_, __, sorter) => {
// 如果 sorter 是数组或者没有字段,直接返回
const single = Array.isArray(sorter) ? sorter[0] : sorter;
const field = single.field as SortField;
// 三态:ascend → descend → null(取消)
if (!single.order) {
// 第三次点击:把 undefined 传出去
onSortChange?.('', '');
return;
}
const order = single.order === 'ascend' ? 'asc' : 'desc';
onSortChange?.(field, order);
};
return (
<>
<Table
columns={columns}
// 其他配置省略
onChange={handleTableChange}
/>
</>
);
};
export default DeviceTable;