如何在Ant Design Table组件中实现拖拽排序自定义数据顺序?
实现Ant Design Table拖拽排序及自定义初始顺序
步骤1:安装依赖
Ant Design Table本身没有内置拖拽排序能力,需要借助react-dnd和react-dnd-html5-backend实现:
npm install react-dnd react-dnd-html5-backend --save
步骤2:改造Table组件
以下是基于现有Table结构的完整修改示例:
import { Table } from 'antd'; import React from 'react'; import { DndProvider, useDrag, useDrop } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; // 封装拖拽行组件 const DraggableRow = ({ index, moveRow, ...restProps }) => { const ref = React.useRef(null); // 拖拽逻辑 const [{ isDragging }, drag] = useDrag({ type: 'TABLE_ROW', item: { index }, collect: monitor => ({ isDragging: monitor.isDragging(), }), }); // 放置逻辑 const [, drop] = useDrop({ accept: 'TABLE_ROW', hover: (item, monitor) => { if (!ref.current) return; const dragIndex = item.index; const hoverIndex = index; // 拖拽自身时不处理 if (dragIndex === hoverIndex) return; // 计算拖拽位置,判断插入方向 const hoverRect = ref.current.getBoundingClientRect(); const hoverMiddleY = (hoverRect.bottom - hoverRect.top) / 2; const clientY = monitor.getClientOffset().y - hoverRect.top; // 过滤无效拖拽场景 if (dragIndex < hoverIndex && clientY < hoverMiddleY) return; if (dragIndex > hoverIndex && clientY > hoverMiddleY) return; // 执行行移动操作 moveRow(dragIndex, hoverIndex); item.index = hoverIndex; }, }); drag(drop(ref)); return ( <tr ref={ref} style={{ opacity: isDragging ? 0.5 : 1, cursor: 'move' }} {...restProps} /> ); }; // 原有列配置 const columns = [ { title: '职位', dataIndex: 'jabatan', key: 'jabatan' }, { title: '姓名', dataIndex: 'name', key: 'name' }, // 其他列保持原有配置不变 ]; const StaffTable = () => { const [data, setData] = React.useState([]); // 初始数据加载及自定义排序处理 React.useEffect(() => { // 模拟从后端获取数据 const fetchedData = [ { key: '1', jabatan: 'Manager', name: '张三', sortOrder: 2 }, { key: '2', jabatan: 'Executive Director', name: '李四', sortOrder: 1 }, { key: '3', jabatan: 'Staff', name: '王五', sortOrder: 3 }, ]; // 优先将Executive Director排到首位,其余按sortOrder字段排序 const sortedData = [...fetchedData].sort((a, b) => { if (a.jabatan === 'Executive Director') return -1; if (b.jabatan === 'Executive Director') return 1; return a.sortOrder - b.sortOrder; }); setData(sortedData); }, []); // 行移动逻辑,同步更新排序字段 const moveRow = (dragIndex, hoverIndex) => { const newData = [...data]; const draggedItem = newData.splice(dragIndex, 1)[0]; newData.splice(hoverIndex, 0, draggedItem); // 更新每项的sortOrder,用于提交到后端保存 const updatedData = newData.map((item, idx) => ({ ...item, sortOrder: idx + 1, })); setData(updatedData); // 提交排序结果到后端(替换为你的实际API地址) // fetch('/api/update-staff-sort', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify(updatedData.map(item => ({ id: item.key, sortOrder: item.sortOrder }))), // }); }; // 自定义Table的行组件 const components = { body: { row: DraggableRow, }, }; // 给拖拽行传递必要参数 const rowProps = (_, index) => ({ index, moveRow, }); return ( <DndProvider backend={HTML5Backend}> <Table columns={columns} dataSource={data} components={components} rowProps={rowProps} /> </DndProvider> ); }; export default StaffTable;
核心关键点说明
- 拖拽逻辑封装:通过
DraggableRow组件统一处理拖拽和放置逻辑,避免业务代码混乱 - 初始排序处理:在数据加载时,通过
sort方法强制将Executive Director排到首位,同时兼容后端返回的sortOrder字段排序 - 排序同步后端:拖拽完成后更新每项的
sortOrder字段,并调用API提交到数据库,确保刷新页面后排序依然生效 - 用户体验优化:拖拽时行半透明显示,鼠标变为移动光标,提升交互感知
注意事项
- 确保数据项有唯一的
key字段,Ant Design Table依赖该字段进行高效渲染 - 若使用服务端分页,拖拽排序仅能在当前页生效;如需全局排序,需加载全量数据或调整后端逻辑
- 可在第一列添加拖拽图标(如
⋮⋮),进一步明确拖拽入口
内容的提问来源于stack exchange,提问作者Esther
相关产品推荐
相关产品推荐

