React 模板封装之拖曳模板 DragTable
前言
前面有介绍过 React 模板封装之基础模板 BaseTable 今天在原先模板的基础上实现一个拖曳模板 DragTable。
一、拖曳模板 DragTable
模板说明:
在原先模板的基础上实现一个进阶版的拖曳模板 DragTable。
效果展示:
以下是正在拖动中的效果
使用场景:
需要在表格中进行拖曳排序。
二、使用案例
参数说明
- modalList :配置接口对应的字段数据集。
- actions:配置接口功能,如配置增删改查接口(url、method、data等)。
- sortSuccess:默认排序接口逻辑是直接传排序后的 id 集合。如果还需要其他的参数或者接口排序逻辑不是这样,则可以使用 sortSuccess 回调函数处理排序接口逻辑。sortSuccess 是拖动排序成功之后的回调(将排序后的 id 集合作为参数)。
需要注意的是在给 modalList 参数时一定要将唯一的 key,比如 id 放在第一列进行配置。因为 id 集合取的字段就是 modalList 集合中的第一列字段。
从以下的案例可知,除了配置之外,只需要写一行代码即可实现如上图的具备增删改查的文章管理功能。
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;
三、API 使用指南
四、源代码
在 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 "../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 这两个库,但是由于版本不同引入的对象可能会有所差异。