使用react-dnd实现表格之间互相拖拽

/** 
引用
immutability-helper 轮子中的 update; 意为:在不改变原始来源的情况下改变数据副本
   useDrag hook提供一种将组件作为拖动源链接到 react-dnd系统中的方法
*/
1
import React, { Component } from 'react'; 2 import { DndProvider, useDrag, useDrop } from 'react-dnd'; 3 import HTML5Backend from 'react-dnd-html5-backend'; 4 import { Table } from 'antd'; 5 import { Form } from '@ant-design/compatible'; 6 import update from 'immutability-helper'; 7 8 const EditableContext = React.createContext(); 9 10 export default class AppIndex extends Component { 11 constructor(props) { 12 super(props); 13 this.state = {
       // 表格1
14 list: [{ id: 1, start: '头下标1', end: '333' }, { id: 2, start: '头下标2', end: '354345' }], 15 newList: [// 表格2 16 { id: 12, start: '头部下标1', end: 'tb' }, 17 { id: 112, start: '头部下标2', end: 'yu' }, 18 ], 19 columns: [ // 表格1 20 { 21 title: '', 22 dataIndex: 'start', 23 }, 24 { 25 title: '', 26 dataIndex: 'end', 27 }, 28 ], 29 newColumns: [ // 表格2 30 {title: '头部', 32 dataIndex: 'start', 33 }, 34 { 35 title: '尾否', 36 dataIndex: 'end', 37 }, 38 ], 39 }; 40 } 41 42 componentWillUnmount() { // 处理内存泄漏问题 43 window.onresize = null; 44 this.setState = () => { 45 return 0; 46 }; 47 } 48 49 /**
     环节拖拽
     @params dragIndex:拖拽表格对应id
    */
50 moveRow = (dragIndex, hoverIndex, dragName, hoverName) => { 51 const { list, newList } = this.state; 52 const { state } = this; 53 if (dragName === 'table2' && dragName !== hoverName) { 54 // 从表2拖 55 this.setState( 56 update(state, { 57 newList: { 58 $splice: [[dragIndex, 1]], 59 }, 60 list: { // hoverIndex为undefined 表示从表2开始拖拽到表1的同时,表1没有数据 61 $splice: 62 hoverIndex === undefined 63 ? [[0, 0, newList[dragIndex]]] 64 : [[hoverIndex, 1, list[hoverIndex]], [hoverIndex, 0, newList[dragIndex]]], 65 }, 66 }) 67 ); 68 } else if (dragName === 'table1' && dragName !== hoverName) { 69 // 从表1拖 70 this.setState( 71 update(state, { 72 list: { 73 $splice: [[dragIndex, 1]], 74 }, 75 newList: { 76 // 从上向下拖拽没问题 第一个数组删,第二个数组增 77 $splice: 78 hoverIndex === undefined 79 ? [[0, 0, list[dragIndex]]] 80 : [[hoverIndex, 1, newList[hoverIndex]], [hoverIndex, 0, list[dragIndex]]], 81 }, 82 }) 83 ); 84 } 85 }; 86 87 render() { 88 const { list, columns, newList, newColumns } = this.state; 89 const typeRow = 'DragbleBodyRow'; 90 const EditableRowDrag = ({index,moveRow,tableName,form,className,style,...restProps }) => { 99 const ref = React.useRef(); 100 const [{ isOver, dropClassName }, drop] = useDrop({ // 开始拖拽 101 accept: typeRow, 102 collect: monitor => { 103 const { index: dragIndex } = monitor.getItem() || {}; 104 if (dragIndex === index) { 105 return {}; 106 } 107 return { 108 isOver: monitor.isOver(), 109 dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward', 110 }; 111 }, 112 drop: item => { 113 if (index === undefined) {// 若被放数据的表中没有数据 则index为undefined 114 this.moveRow(item.index, index, item.tableName, tableName); 115 } else { 116 moveRow(item.index, index, item.tableName, tableName); 117 } 118 }, 119 }); 120 const [, drag] = useDrag({ // 准备放下 121 item: { type: typeRow, index, tableName },
        // 收集功能,一个函数,用来收集属性的,返回一个js对象,并且返回值会合并到你的组件属性中 ;monitor:监听器
        // monitor 里面存放的是一些拖动的状态,当拖动状态发生变化时会通知属性重新获取属性 并重新刷新组件
122         collect: monitor => ({
123           isDragging: monitor.isDragging(),
124         }),
125       });
126       drop(drag(ref));
127       return (
128         <EditableContext.Provider value={form}>
129           <tr
130             ref={ref}
131             className={`${className}${isOver ? dropClassName : ''}`}
132             style={{ cursor: 'move', ...style }}
133             {...restProps}
134           />
135         </EditableContext.Provider>
136       );
137     };
138     const EditableFormRowDrag = Form.create()(EditableRowDrag);
139     const components = {
140       // header: {
141       //   cell: ResizeableTitle,
142       // },
143       body: {
144         row: EditableFormRowDrag,
145         //   cell: EditableCell,
146       },
147     };
148 
149     const NewTable = (
150       <>
151         <Table
152           components={components}
153           rowKey="id"
154           dataSource={list}
155           columns={columns}
156           pagination={false}
157           onRow={(record, index) => ({
158             index,
159             moveRow: this.moveRow,
160             tableName: 'table1', // 表格唯一标识
161           })}
162         />
163         <br />
164         <Table
165           components={components}
166           rowKey={'id' || Math.random()}
167           dataSource={newList}
168           columns={newColumns}
169           pagination={false}
170           onRow={(record, index) => {
171             return {
172               index,
173               moveRow: this.moveRow,
174               tableName: 'table2', // 表格唯一标识
175             };
176           }}
177         />
178       </>
179     );
180     return <DndProvider backend={HTML5Backend}>{NewTable}</DndProvider>;
181   }
182 }

 效果展示

 

posted on 2024-02-05 13:30  imi小码娜  阅读(140)  评论(0编辑  收藏  举报

导航