You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;

核心关键点说明

  1. 拖拽逻辑封装:通过DraggableRow组件统一处理拖拽和放置逻辑,避免业务代码混乱
  2. 初始排序处理:在数据加载时,通过sort方法强制将Executive Director排到首位,同时兼容后端返回的sortOrder字段排序
  3. 排序同步后端:拖拽完成后更新每项的sortOrder字段,并调用API提交到数据库,确保刷新页面后排序依然生效
  4. 用户体验优化:拖拽时行半透明显示,鼠标变为移动光标,提升交互感知

注意事项

  • 确保数据项有唯一的key字段,Ant Design Table依赖该字段进行高效渲染
  • 若使用服务端分页,拖拽排序仅能在当前页生效;如需全局排序,需加载全量数据或调整后端逻辑
  • 可在第一列添加拖拽图标(如⋮⋮),进一步明确拖拽入口

内容的提问来源于stack exchange,提问作者Esther

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:15:11