14 minutes read

React-dnd 实现无限子集的拖拽构建功能(多层嵌套)


GaryLyu
15/07/2023 12:22 AM

最近开发的指纹浏览器NestBrowser 有个拖拽方式建立自动化流程的功能, 使用了react-dnd 这个库, 记录一下 react-dnd的多层嵌套使用

核心是使用递归的方式来索引数据, 如果数据量大, 建议使用自维护的索引方式

代码量较大, 本blog主讲思路和核心代码,其他结合各自业务开发

  • 技术栈 electron, nodejs, react, typescript
  • npm库 react-dnd
  • Ui 组件 material-ui

Config: 最终需要形成的数据

拖拽件(drag)生成唯一uuid来标识,进行排序定位等处理

递归算法:
/**
*
* @param configs 配置数组
* @param id 拖动的drag id
* @param toId 拖到的drop id
* @param isOverMid 在拖到drop的上或下插入
* @param toChild 是否是拖到子组件里面
* @returns 返回新的配置数组
*/
export const moveConfig = (
configs: AutomationConfigProps[],
id: string,
toId: string,
isOverMid = true, // 前后
toChild = false,
): AutomationConfigProps[] => void;
export const addConfigToId = (
configs: AutomationConfigProps[],
config: AutomationConfigProps,
toId: string,
isOverMid = true,
toChild = false,
): boolean => void;
export const deleteConfigById = (
configs: AutomationConfigProps[],
id: string,
): boolean => void;
export const getConfigById = (
configs: AutomationConfigProps[],
id: string,
): AutomationConfigProps => void;
export const editConfigById = (
configs: AutomationConfigProps[],
id: string,
config: AutomationConfigProps,
): boolean => void;
useGrag 使用
() => ({
type: AutomationItemTypes.SORT_BOX, // 常量, 结合Drop使用,声明drag可放置到的区域
item: dragCard, // 数据格式, Drop 能接收到的参数
end: (item, monitor) => { // 完成放置
......
// source 为每个drop响应父标识,用于处理新增件到哪个父类
......
const [...newConfig] = config;
// 新增组件
if (source === EMPTY_DROP_BASE) {
newConfig.push(addData);
setConfig(newConfig);
}
......
// 排序新增
const res = addConfigToId(
newConfig,
addData,
sortBoxDrop.dragToId,
sortBoxDrop.isOverMid,
);
if (res === true) setConfig(newConfig);
else
console.log('DragItem.tsx addConfigToId fail: ');
}
},
collect: (monitor) => ({
isDragging: monitor.isDragging(),
handlerId: monitor.getHandlerId(),
}),
}),
[config, setConfig],
);
useDrop 使用
const [{ isOver, isOverCurrent, canDrop }, drop] = useDrop(
() => ({
accept: AutomationItemTypes.SORT_BOX, // 和drag保持一致
collect: (monitor) => ({
isOver: monitor.isOver(),
isOverCurrent: monitor.isOver({ shallow: true }),
canDrop: monitor.canDrop(),
}),
drop: (item, monitor) => {
const didDrop = monitor.didDrop();
// 父子嵌套的drop,子drop处理
if (didDrop) {
return;
}
// hover 更新了 sortBoxDrop, 这里不在处理
return { source }; // source为已放置的件uuid或自定义的区域
},
hover({ id: draggedId }: Item, monitor) {
// 计算拖拽件放置到的地方 isOverMid: 放置前or后
......
dropCbDragTo(id, isOverMid);
}
},
}),
[dropCbDragTo, config, setConfig],
);

GaryLyu

Leader

Nestbrowser(蜂巢浏览器) 可自定义所有参数来隐藏和控制您的数字指纹。您可以模仿真实的 Internet 身份。 Nestbrowser 帮助您创建大量配置文件, 每个配置文件都有自己的数字指纹。这些配置文件彼此不重叠, 因此网站不会禁止您的帐户。这对于执行各种任务非常有用在网上。

Member since Mar 15, 2021


最近文章

React-dnd 实现无限子集的拖拽构建功能(多层嵌套)
15 Jul 202314 minutes read
查看所有文章