在react项目中使用dnd实现一个简单的拖拽排序功能
首先简单的介绍一下dnd:
React-DnD是一组React实用程序,可帮助您构建复杂的拖放界面,同时保持组件之间的耦合。
1、DndProvider组件为您的应用程序提供React-DnD功能。必须通过backendc参数将其注入后端,但是也可以将其注入window对象。
backend后端是React-DnD中非常好的一种设计方法。可以理解为具体拖拽的实现方式
2、userDrag声明拖动源
userDrag用于将当前组件用作拖动源的钩子。
3、userDrop声明放置源
useDrop用于使用当前组件作为放置目标的钩子。
下面是具体实现拖拽功能的组件代码
import React, { useRef } from 'react';
import { useDrop, useDrag } from 'react-dnd';
// dnd拖拽排序
export default (props: any) => {
const { moveRow, index, children } = props;
const ref: any = useRef(null);
const accept = 'DragDropBox';
const [{ isOver, dropClassName }, drop] = useDrop({
accept,
collect: (monitor) => {
const { index: dragIndex } = (monitor.getItem() || {}) as any;
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: (item: any) => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
type: accept,
item: { index },
collect: (monitor: any) => ({
isDragging: monitor.isDragging(),
}),
});
const changeRef = drag(drop(ref));
return (
<div
// @ts-ignore
ref={changeRef}
key={index + 1}
className={`${isOver ? dropClassName : ''}`}
>
<span key={index}>{children}</span>
</div>
);
};
使用时
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import ReactDndDragSort from './drag';
import { useCallback} from 'react';
const moveRow = useCallback(
(dragIndex, hoverIndex) => {
const newItems = [...textValue];
newItems.splice(hoverIndex, 1, ...newItems.splice(dragIndex, 1, newItems[hoverIndex]));
onChange?.(newItems);
},
[textValue],
);
<DndProvider backend={HTML5Backend}>
<WSpace size={'large'}>
{textValue.map((item: string, index: number) => {
return (
<div key={index}>
<ReactDndDragSort index={index} moveRow={moveRow}>
<div>需要拖拽的模块</div>
</ReactDndDragSort>
</div>
);
})}
</WSpace>
</DndProvider>