分享起因

因为我的项目中须要应用拖曳组件(需要:全局,跨组件,跨数据),我抉择了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"              />                   }