功能点:
1.表格内的行拖拽(drag和drop都放在行上)
2.跨表格的行拖拽(drag事件都放在行上,表格不空时drop事件放在行上,表格空时drop事件放在空提示上)
3.表格拖拽(drag和drop都放在表格的header上)
MytableV3.js
import React from "react";
import { Table, ConfigProvider, Icon } from "antd";
import { DndProvider, DragSource, DropTarget } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import update from "immutability-helper";
import uuid from "uuid";
let dragingIndex = -1;
class BodyRow extends React.Component {
render() {
const {
isOver,
connectDragSource,
connectDropTarget,
moveRow,
delRow,
...restProps
} = this.props;
const style = { ...restProps.style, cursor: "move" };
let { className } = restProps;
if (isOver) {
if (restProps.index > dragingIndex) {
className += " drop-over-downward";
}
if (restProps.index < dragingIndex) {
className += " drop-over-upward";
}
}
return connectDragSource(
connectDropTarget(
<tr {...restProps} className={className} style={style} />
)
);
}
}
class HeaderRow extends React.Component {
render() {
const {
isOver,
connectDragSource,
connectDropTarget,
moveRow,
delRow,
...restProps
} = this.props;
const style = { ...restProps.style, cursor: "move" };
return connectDragSource(
connectDropTarget(<tr {...restProps} style={style} />)
);
}
}
class EmptyBody extends React.Component {
render() {
const { isOver, connectDragSource, connectDropTarget, ...restProps } =
this.props;
return connectDragSource(
connectDropTarget(
<div style={{ textAlign: "center" }}>
<Icon type="smile" style={{ fontSize: 20 }} />
<p>空状态信息提示</p>
</div>
)
);
}
}
const rowSource = {
beginDrag(props) {
// debugger;
dragingIndex = props.index;
return {
index: props.index,
record: props.record,
tablekey: props.tablekey,
};
},
endDrag(props, monitor) {
// DragSourceMonitor
// monitor.canDrag(); // 是否能被拖拽
// monitor.isDragging(); // 是否正在拖拽
// monitor.getItemType(); // 拖拽组件type
// monitor.getItem(); // 当前拖拽的item
// monitor.getDropResult(); // 查询drop结果
// monitor.didDrop(); // source是否已经drop在target
// monitor.getInitialClientOffset(); // 拖拽组件初始拖拽时offset
// monitor.getInitialSourceClientOffset();
// monitor.getClientOffset(); // 拖拽组件当前offset
// monitor.getDifferenceFromInitialOffset(); // 当前拖拽offset和初始拖拽offset的差别
// monitor.getSourceClientOffset();
const dragKey = props.tablekey;
const hoverKey = monitor.getItem().tablekey;
const dragIndex = props.index;
// const hoverIndex = monitor.getItem().index;
// const dragRecord = props.record;
// const hoverRecord = monitor.getItem().record;
if (dragKey !== hoverKey) {
props.delRow(dragIndex);
}
},
};
const rowTarget = {
drop(props, monitor) {
// DropTargetMonitor
// monitor.canDrop() // 是否可被放置
// monitor.isOver(options) // source是否在target上方
// monitor.getItemType() // 拖拽组件type
// monitor.getItem() // 当前拖拽的item
// monitor.getDropResult() // 查询drop结果
// monitor.didDrop() // source是否已经drop在target
// monitor.getInitialClientOffset() // 拖拽组件初始拖拽时offset
// monitor.getInitialSourceClientOffset()
// monitor.getClientOffset() // 拖拽组件当前offset
// monitor.getDifferenceFromInitialOffset() // 当前拖拽offset和初始拖拽offset的差别
// monitor.getSourceClientOffset()
// debugger
const dragKey = monitor.getItem().tablekey;
const hoverKey = props.tablekey;
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;
const dragRecord = monitor.getItem().record;
const hoverRecord = props.record;
// Don't replace items with themselves
if (dragIndex === hoverIndex && dragKey === hoverKey) {
return;
}
// Time to actually perform the action
props.moveRow(
dragIndex,
hoverIndex,
dragKey,
hoverKey,
dragRecord,
hoverRecord
);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
monitor.getItem().index = hoverIndex;
monitor.getItem().record = props.record;
monitor.getItem().tablekey = props.tablekey;
},
};
const myTarget = {
drop(props, monitor) {
const { record } = monitor.getItem();
props.inRow(record);
monitor.getItem().index = props.index;
monitor.getItem().record = props.record;
monitor.getItem().tablekey = props.tablekey;
},
};
const headerTarget = {
drop(props, monitor) {
const dragKey = monitor.getItem().tablekey
const dropKey = props.tablekey
props.moveTable(dragKey,dropKey);
},
};
const headerSource = {
beginDrag(props, monitor) {
return {
tablekey: props.tablekey,
};
},
};
const DragableBodyRow = DropTarget("row", rowTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
}))(
DragSource("row", rowSource, (connect) => ({
connectDragSource: connect.dragSource(),
}))(BodyRow)
);
const DragableHeaderRow = DropTarget(
"header",
headerTarget,
(connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
})
)(
DragSource("header", headerSource, (connect) => ({
connectDragSource: connect.dragSource(),
}))(HeaderRow)
);
const EmptyBodyC = DropTarget("row", myTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
}))(
DragSource("row", rowSource, (connect) => ({
connectDragSource: connect.dragSource(),
}))(EmptyBody)
);
const columns = [
{
title: "Name",
dataIndex: "name",
key: "name",
},
{
title: "Age",
dataIndex: "age",
key: "age",
},
{
title: "Address",
dataIndex: "address",
key: "address",
},
];
const datas1 = [
{
key: uuid(),
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park",
},
{
key: uuid(),
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park",
},
{
key: uuid(),
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
},
];
const datas2 = [
{
key: uuid(),
name: "张三",
age: 32,
address: "New York No. 1 Lake Park",
},
{
key: uuid(),
name: "李四",
age: 42,
address: "London No. 1 Lake Park",
},
{
key: uuid(),
name: "王五",
age: 32,
address: "Sidney No. 1 Lake Park",
},
];
class DragSortingTable extends React.Component {
state = {
data: this.props.tablekey === "111" ? datas1 : datas2,
};
components = {
header: {
row: DragableHeaderRow,
},
body: {
row: DragableBodyRow,
},
};
moveRow = (
dragIndex,
hoverIndex,
dragKey,
hoverKey,
dragRecord,
hoverRecord
) => {
const { data } = this.state;
if (dragKey === hoverKey) {
const dragRow = data[dragIndex];
this.setState(
update(this.state, {
data: {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRow],
],
},
})
);
} else {
this.setState(
update(this.state, {
data: {
$splice: [[hoverIndex + 1, 0, dragRecord]],
},
})
);
}
};
delRow = (dragIndex) => {
// const { data } = this.state;
// const dragRow = data[dragIndex];
this.setState(
update(this.state, {
data: {
$splice: [[dragIndex, 1]],
},
})
);
};
inRow = (record) => {
this.setState(
update(this.state, {
data: {
$push: [record],
},
})
);
};
moveTable = (dragKey,dropKey)=>{
this.props.changeIndex(dragKey,dropKey)
}
render() {
const data = this.props.tablekey === "111" ? datas1 : datas2
if (this.state.data.length) {
return (
<DndProvider backend={HTML5Backend}>
<Table
columns={columns}
// dataSource={this.state.data}
dataSource={data}
components={this.components}
onRow={(record, index) => ({
index,
record: record,
moveRow: this.moveRow,
delRow: this.delRow,
tablekey: this.props.tablekey,
})}
onHeaderRow={(record, index) => ({
index,
record,
moveTable: this.moveTable,
tablekey: this.props.tablekey,
})}
/>
</DndProvider>
);
} else {
// const customizeRenderEmpty = () => (
// //这里面就是我们自己定义的空状态
// <div style={{ textAlign: "center" }}>
// <Icon type="smile" style={{ fontSize: 20 }} />
// <p>空状态信息提示</p>
// </div>
// );
const customizeRenderEmpty = () => (
//这里面就是我们自己定义的空状态
<EmptyBodyC inRow={this.inRow} delRow={this.delRow} />
);
return (
<DndProvider backend={HTML5Backend}>
<ConfigProvider renderEmpty={customizeRenderEmpty}>
<Table columns={columns} dataSource={this.state.data} />
</ConfigProvider>
</DndProvider>
);
}
}
}
export default DragSortingTable;
Drag.js
import "antd/dist/antd.css";
import React, { Component } from "react";
import DragSortingTable from "./components/MytableV3";
class Drag extends Component {
constructor(props) {
super(props);
this.state = {
keys: ["111", "222"],
};
}
changeIndexH = (dragKey, dropKey) => {
const dragIndex = this.state.keys.findIndex((item) => item === dragKey);
const dropIndex = this.state.keys.findIndex((item) => item === dropKey);
const keys = [...this.state.keys];
keys.splice(dragIndex, 1);
keys.splice(dropIndex, 0, this.state.keys[dragIndex]);
this.setState({
keys,
});
};
render() {
const $LIST = this.state.keys.map((item) => {
return (
<DragSortingTable
tablekey={item}
changeIndex={(dragKey, dropKey) => {
this.changeIndexH(dragKey, dropKey);
}}
/>
);
});
return (
<div>{$LIST}</div>
);
}
}
export default Drag;