react-sortablejs文档地址:Sortable.js中文网,这个库的优点是语法很简单,通常是用在两个组件之间相互拖拽的功能,拖拽的组件可定制,自由度很高,很适合拖拽组件很复杂的情况

antd官网上推荐使用react-dnd来进行table行拖拽,但这个库很容易出现一下问题

常见的解决方案是,添加一个唯一的key进行标识

由于此次需求中同一个父组件里有react-sortablejs实现的两个组件相互拖拽的功能,还需要有table进行行拖拽,添加key值的方式解决不了上面出现的这个问题,只能换掉react-dnd,使用react-sortablejs进行重写,废话不多说,下面是完整的代码,

import { Table } from 'antd';
import { ReactSortable } from 'react-sortablejs';
import styles from './table.less';

const DropTable = (props: any) => {
  const { columns, dataSource, setDataSource, setSelectedRow, selectedRow } =
    props;

  const onDragEnd = (result) => {
    console.log('结束');
  };

  const DraggableBodyRow = ({ children, ...restProps }) => {
    return <tr {...restProps}>{children}</tr>;
  };

  const DraggableBody = ({ children, ...restProps }) => {
    return (
      <ReactSortable
        tag={'tbody'}
        key={restProps.key}
        list={dataSource}
        setList={(evt) => {
          // console.log(evt);
          console.log('移动');
        }}
        group={{ name: 'dropBox', put: false, pull: false }}
        animation={150}
        scroll={true}
        onStart={() => {
          console.log('start');
        }}
        onEnd={onDragEnd}
        {...restProps}
      >
        {children}
      </ReactSortable>
    );
  };

  const components = {
    body: {
      wrapper: DraggableBody,
      row: DraggableBodyRow,
    },
  };

  const rowClassName = (record: any) => {
    return selectedRow.id === record.id ? `selectRowStyle` : '';
  };

  return (
    <div className={styles.drogTable}>
      <Table
        columns={columns}
        dataSource={dataSource}
        pagination={false}
        components={components}
        rowKey={'id'}
        size={'small'}
        scroll={{ y: '100%' }}
        rowClassName={(record) => {
          const result = rowClassName(record);
          return result;
        }}
        onRow={(record, index) => ({
          index,
          key: record.id, // 确保 key 是唯一的
          moveRow: onDragEnd,
          record,
          data: dataSource,
          itemTypes: 'DraggableBodyRow',
          onClick: (e) => {
            e.stopPropagation();
            setSelectedRow(record);
          },
        })}
      />
    </div>
  );
};

export default DropTable;

给该组件传递datasource以及columns就可以使用,onsort函数在任何操作下都会调用,所以一般使用onend进行判断拖拽完成并进行下面的操作,代码中添加了点击行之后变色的功能,不需要可以将onRow的onClick函数去掉

注意,由于这样嵌套打乱了table的结构,setList中获取到的evt中多了一个undefined的值,导致无法直接获取到排序完成的值,可以借助onEnd回调函数中的参数result中以下两个参数标记的旧下标和新下标去调换顺序(因为undefined的缘故导致下标从1开始),这种方式暂时运行是稳定的不确定是否有风险,最好的解决办法就是使用html原生代码手搓table以适配这个库的嵌套方式(手搓table代码:HTML原生手搓带滚动条table-CSDN博客)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐