react-dnd实现任意拖动与互换位置

Ros ·
更新时间:2024-11-14
· 385 次阅读

本文实例为大家分享了react-dnd实现任意拖动与互换位置的具体代码,供大家参考,具体内容如下

react-dnd用法

hooks组件

1.使用DndProvider定义一个可以拖拽的范围

import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider } from 'react-dnd'; class App extends Component{   render () {     return (       <div>         <DndProvider backend={HTML5Backend}>           <Container />         </DndProvider>       </div>     )   } }

2.定义drag和drop

drag:就是可以被拖拽的东西

drop: 就是拖拽后可以放的地方

import { useDrag } from 'react-dnd'; /**item:必填。描述了要拖动的数据 ( 包含type: 对应drop>accept ) begin(monitor): 可选的。拖动操作开始时触发。 end(item, monitor): 可选的。当拖动停止时,end被调用。 canDrag(monitor): 可选的。使用它来指定当前是否允许拖动。 isDragging(monitor): 可选的。默认情况下,只有启动拖动操作的拖动源才被视为拖动。 collect: 可选的。收集功能。它应该返回道具的简单对象以返回注入到组件中。它接收两个参数,monitor和props。 spec:必填。一个普通的JavaScript对象,上面有一些允许的方法。它描述了拖动源如何对拖放事件做出反应。**/ const Drag = ({ name }) => {   const [{isDragging}, drag] = useDrag({     type: 'test',     end(item, monitor) {            monitor.getDropResult()   //获取拖拽对象所处容器的数据         monitor.didDrop()    // 当前容器能否放置拖拽对象     }       })   return (     <div id="drag">{name}</div>   ) } import { useDrop } from 'react-dnd'; /** 参考api  accept:必填。 (对应 drag item.type ) options: 可选的。一个普通的对象。 drop(item, monitor): 可选的。当兼容项目放在目标上时调用。 hover(item, monitor): 可选的。将项目悬停在组件上时调用。 canDrop(item, monitor): 可选的。使用它来指定放置目标是否能够接受该物品。如果要始终允许它,则只需忽略此方法。 collect: 可选的。收集功能。它应该返回道具的简单对象以返回注入到组件中。它接收两个参数,monitor和props */ const Container = (props) => {   const [{isOver, canDrop}, drop] = useDrop({     accept: 'test',     drop: (item, monitor) => ({          dropname: '测试',          top: monitor.getDifferenceFromInitialOffset().y,         left: monitor.getDifferenceFromInitialOffset().x       }),       // 可以在这里配置数据,与drag中monitor.getDropResult()获取的信息关联     collect: (monitor) => ({       isOver: monitor.isOver(),   // 返回拖拽对象是否悬浮在该容器上       canDrop: monitor.canDrop(),  // 当前容器是否支持拖拽对象放置     })   })   return (     <div ref={drop}>         ...     </div>   ) } 实现任意拖拽

1.在容器中通过drop —> monitor.getDifferenceFromInitialOffset()获取拖拽对象当前位置与初始位置的偏移量

2.在drag的end中,通过monitor.getDropResult()获取到与初始位置的偏移量,给当前拖拽元素的偏移量重新赋值,即可做到任意拖拽

3.如果同时有很多个可拖拽的对象,需要给他们定义一个index值, 因为这个可拖拽组件是复用的,所以我们获取到的拖拽对象是个数组,我们可以用index作为下标,给当前拖拽组件单独赋值

const Drag = ({ name, top, left, index }) => {   const [{isDragging}, drag] = useDrag({     type: 'test',     end(item, monitor) {       console.log(item);       if(monitor.didDrop()){         const droptarget = monitor.getDropResult();         const top = document.querySelectorAll('#drag')[index].offsetTop;         const left = document.querySelectorAll('#drag')[index].offsetLeft;         document.querySelectorAll('#drag')[index].style.top = (top + droptarget.top) + 'px';         document.querySelectorAll('#drag')[index].style.left = (left + droptarget.left) + 'px';       }else{         console.log(monitor.getDropResult());       }     }   })   return (     <div id="drag" index={index} ref={drag} style={{position: 'absolute', top: `${top}`, left: `${left}`, width: '70px', height: '40px', border: '1px solid black'}}>{name}</div>   ) } const Container = (props) => {   const [{isOver, canDrop}, drop] = useDrop({     accept: 'test',     drop: (item, monitor) => ({ dropname: '测试', top: monitor.getDifferenceFromInitialOffset().y, left: monitor.getDifferenceFromInitialOffset().x }),     collect: (monitor) => ({       isOver: monitor.isOver(),       canDrop: monitor.canDrop(),     })   })   return (     <div       id="drop1"       ref={drop}       style={{width: '700px', height: '600px', backgroundColor: 'yellow'}}     >     </div>   ) }

拖拽互换位置

拖拽互换位置需要组件既是drag拖拽对象,也是drop拖拽容器。所以使用useRef()定义ref,然后 drag(drop(ref)),让它即作为拖拽对象也作为拖拽容器,然后定义拖拽结束事件

import React, { useRef, useMemo } from 'react'; import { useDrag, useDrop } from 'react-dnd'; import { item } from './itemType'; const style = {   display: 'inline',   border: '1px dashed gray',   padding: '0.5rem 1rem',   marginRight: '30px',   marginTop: '.5rem',   backgroundColor: 'blue',   cursor: 'move',   borderRadius: '50%',   position: 'relative', }; const Drag = (props) => {   const ref = useRef()   const [{}, drop] = useDrop({     accept: item.type,     drop: (item, monitor) => {         return {           index: props.index         }     }   })   const count = useMemo(() => {     document.getElementById('delete').oncontextmenu = (e) => {       e.preventDefault();     }   },[1])   const [{}, drag] = useDrag({     type: item.type,     end: (item, monitor) => {       console.log(monitor.didDrop());       if(monitor.didDrop()){         const dropResult = monitor.getDropResult();         props.changePosition([props.index, dropResult.index])       }else{         return;       }     }   })   drag(drop(ref))   return (     <div id="delete" ref={ref} id="drag" index={props.index} style={{...style}} >       <span>{props.name}</span>       <span style={{position: 'absolute', border: '1px solid gray', top: "18.5px", left: '145px', width: '29px',background: 'gray'}}></span>     </div>   ) }



React

需要 登录 后方可回复, 如果你还没有账号请 注册新账号