前面有介绍过 React 模板封装之基础模板 BaseTable 今天在原先模板的基础上实现一个拖曳模板 DragTable。
模板说明:
在原先模板的基础上实现一个进阶版的拖曳模板 DragTable。
效果展示:
以下是正在拖动中的效果
使用场景:
需要在表格中进行拖曳排序。
参数说明
从以下的案例可知,除了配置之外,只需要写一行代码即可实现如上图的具备增删改查的文章管理功能。
import React from "react";
import BaseTable from "../../../../template/BaseTable/index";
const modalList= [
{
label:"栏目ID", field:"columnId",renderType:"Input",visible:true,writable:true,},
{
label:"栏目名称",field:"columnName",renderType:'Input',require:true,visible:true},
{
label:"栏目描述",field:"description",renderType:'Input',require:true,visible:true},
]
const actions = [
{
status:"sort",
name:'排序',
url: "/admin/weeksPeriodicalColumn/sort",
method: 'post',
showColumn:false,
data:{
columnId:"",
}
},
{
status:"query",
name:'查询',
url: "/admin/weeksPeriodicalColumn/columnList",
extraField:"list",
method: 'post',
showColumn:false
}
];
function Columns(){
return (
<DragTable
actions={
actions}
modalList={
modalList}
/>
);
}
export default Columns;
参考 React 模板封装之基础模板 BaseTable
在 DragTable 目录中包含如下文件。
index.js
import React from "react";
import {
DndProvider, useDrag, useDrop } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import BaseTable from "../BaseTable/index";
import update from "immutability-helper";
import {
editAPI } from "utils/commonApi";
import {
useRef, useImperativeHandle } from "react";
const type = "DragableBodyRow";
const DragableBodyRow = ({
index,
moveRow,
className,
style,
...restProps
}) => {
const ref = React.useRef();
const [{
isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: (monitor) => {
const {
index: dragIndex } = monitor.getItem() || {
};
if (dragIndex === index) {
return {
};
}
return {
isOver: monitor.isOver(),
};
},
drop: (item) => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
item: {
type, index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
return (
<tr
ref={
ref}
className={
`${
className}${
isOver ? dropClassName : ""}`}
style={
{
cursor: "move", ...style }}
{
...restProps}
/>
);
};
const components = {
body: {
row: DragableBodyRow,
},
};
const moveRow = (baseTableRef, props, dragIndex, hoverIndex) => {
let that = baseTableRef.current;
const {
dataSource, setDataSource } = that;
const dragRow = dataSource[dragIndex];
let {
modalList } = props;
setDataSource((dataSource) => {
let newData = update(dataSource, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRow],
],
});
let columnIdList = [];
newData.map((item) => {
columnIdList.push(item[modalList[0].field]);
});
const {
sortSuccess } = props;
if (sortSuccess) {
//自定义调排序接口
sortSuccess(columnIdList);
} else {
//默认调排序接口
let {
actions, modalList } = props;
let action = actions.filter((item) => item.status === "sort")[0];
let data = action.data;
for (let i in data) {
data[i] = columnIdList;
}
editAPI(action, modalList, data);
}
return newData;
});
};
function DragTable(props, ref) {
const {
actions, modalList } = props;
return (
<DndProvider backend={
HTML5Backend}>
<BaseTable
actions={
actions}
modalList={
modalList}
components={
components}
onRow={
(record, index) => ({
index,
moveRow: moveRow.bind(this, baseTableRef, props),
})}
/>
</DndProvider>
);
}
export default React.forwardRef(DragTable);
以上可能有部分关联的JS文件没贴出来,因文件太多,就不一一贴出,需要的请留言。
注意1:
配置 modalList 时一定要将唯一key放在第一行。
注意2:
接口排序逻辑默认上传排序后的 id 集合即可。如果还需要上传其他字段或者是不一样的排序逻辑,则需要使用 sortSuccess 回调函数,在该函数中调用排序接口或者进行其他操作。
注意3:
排序主要依赖 react-dnd 和 react-dnd-html5-backend 这两个库,但是由于版本不同引入的对象可能会有所差异。