分享起因
因为我的项目中须要应用拖曳组件(需要:全局,跨组件,跨数据),我抉择了react-dnd
概念
React DnD 是一组 React 高阶组件,咱们在应用的时候只须要将指标元素进行包裹,就能够实现目标元素具备拖动或承受拖动的性能。它将整个拖动的事件残缺的形容了进去,这使得咱们在应用的过程变得简略易用和扩大上有了有限的可能,在解决简单拖曳和丰盛需要的时候强烈建议应用它。
官网 https://react-dnd.github.io/r...
根本
- Item type:跟redux或其余组件一样,item用来形容拖动dom的数据对象,type用来标识一组可拖动和接管
- Backend:用来体现dom拖动景象,我应用了HTML5Backend
- Monitors:用来查问以后拖动状态(数据,dom,地位等),弱小的收集性能
- Connectors:用于Backend和组件状态之间的连贯
hook:useDrag 将组件作为可拖动的起源注册到dnd useDrop 将组件作为可接管拖动起源注册到dnd
应用办法
导入
npm install react-dnd react-dnd-html5-backend
初始化import { HTML5Backend } from 'react-dnd-html5-backend'; <DndProvider backend={HTML5Backend}> .... </>
组件参数type.ts
export type DragProps = { name: string; //名称标记 type: string; //暂用于标记拖拽类型,接收者和发送者统一 role: string; // data: any; //绑定的数据用于拖曳后操作数据 content: JSX.Element; //绑定的元素 onDragFinished: Function; //拖动完结回调.};export type AcceptorProps = { name: string; //名称标记 type: string; //暂用于标记拖拽类型,接收者和发送者统一 role: string; // data: any; //绑定的数据用于拖曳后操作数据 content: JSX.Element; //绑定的元素 styleType: 'background' | 'border'; // customStyle:{ // canDrop:string, // isActive:string // } onHover: Function; //移入区域.};
组件MyDrag.ts
import { useDrag, useDrop } from 'react-dnd';import { DragProps, AcceptorProps } from './type';export const Dragger = function Dragger(option: DragProps) { const { name, data, type, onDragFinished } = option; const [{ isDragging }, drag] = useDrag(() => ({ type: type, item: { name: name, data: data }, end: (item, monitor, ...arg) => { console.log(arg); const dropResult = monitor.getDropResult(); if (item && dropResult) { console.log('source:', item); console.log('target:', dropResult); } if (onDragFinished) { onDragFinished(item, dropResult); } }, collect: (monitor) => ({ isDragging: monitor.isDragging(), handlerId: monitor.getHandlerId(), }), })); const opacity = isDragging ? 0.4 : 1; return ( <div ref={drag} role={option.role} style={{ opacity }} data-id={`${option.name}`} > {option.content} </div> );};export const Acceptor = (option: AcceptorProps) => { const { name, data, type, styleType, onHover } = option; const [{ canDrop, isOver }, drop] = useDrop(() => ({ accept: type, drop: () => option, hover: () => { if (onHover) { onHover(); } }, collect: (monitor) => ({ isOver: monitor.isOver(), canDrop: monitor.canDrop(), }), })); const isActive = canDrop && isOver; let backgroundColor = '#222'; let borderBottom = '0px solid rgba(31, 92, 206, 0)'; if (isActive) { backgroundColor = 'rgba(64, 224, 208, 0.3)'; borderBottom = '1px solid #26BD11'; } else if (canDrop) { backgroundColor = 'rgba(100, 149, 277, 0.3)'; borderBottom = '1px solid #2063AF'; } return ( <div ref={drop} role={'Acceptor'} style={ styleType === 'background' ? { backgroundColor } : { borderBottom } } > {option.content} </div> );};//同一list之间拖动export const dragList = ( list: Array<any>, crtIndex: number, willIndex: number,) => { let targetItem = list[crtIndex]; let delIndex = crtIndex < willIndex ? crtIndex : crtIndex + 1; list.splice(willIndex, 0, targetItem); list.splice(delIndex, 1); return list;};//来自不同list之间拖动,1.删除原来 2不删除原来export const dragToList = ( list: Array<any>, targetList: Array<any>, crtIndex: number, willIndex: number, del: 1 | 2,) => { let targetItem = list[crtIndex]; targetList.splice(willIndex, 0, targetItem); if (del === 1) { list.splice(crtIndex, 1); } return { list, targetList };};
具体应用
import { Dragger, Acceptor, dragList } from '@/components/Drag';//同列表之间拖曳 handleDrag(crt: number, target: number) { conslog.log(dragList(newPanels, crt, target);) } renderDrag(item: ItemProps, children) { <Acceptor key={item.type} name={item.title} data={item} type="xxx" role="xxxAccept" onHover={() => {}} content={ <Dragger name={item.title} data={item} type="xxx" role="xxxDrag" content={children} onDragFinished={(source: any, target: any) => { console.log(source, target, '回调'); if (target) { this.handleDrag( source.data.sort, target.data.sort, ); } }} /> } styleType="border" /> }