react-dnd實(shí)現(xiàn)任意拖動(dòng)與互換位置
本文實(shí)例為大家分享了react-dnd實(shí)現(xiàn)任意拖動(dòng)與互換位置的具體代碼,供大家參考,具體內(nèi)容如下
react-dnd用法
hooks組件
1.使用DndProvider定義一個(gè)可以拖拽的范圍
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:必填。描述了要拖動(dòng)的數(shù)據(jù) ( 包含type: 對(duì)應(yīng)drop>accept ) begin(monitor): 可選的。拖動(dòng)操作開(kāi)始時(shí)觸發(fā)。 end(item, monitor): 可選的。當(dāng)拖動(dòng)停止時(shí),end被調(diào)用。 canDrag(monitor): 可選的。使用它來(lái)指定當(dāng)前是否允許拖動(dòng)。 isDragging(monitor): 可選的。默認(rèn)情況下,只有啟動(dòng)拖動(dòng)操作的拖動(dòng)源才被視為拖動(dòng)。 collect: 可選的。收集功能。它應(yīng)該返回道具的簡(jiǎn)單對(duì)象以返回注入到組件中。它接收兩個(gè)參數(shù),monitor和props。 spec:必填。一個(gè)普通的JavaScript對(duì)象,上面有一些允許的方法。它描述了拖動(dòng)源如何對(duì)拖放事件做出反應(yīng)。**/ const Drag = ({ name }) => { ? const [{isDragging}, drag] = useDrag({ ? ? type: 'test', ? ? end(item, monitor) { ?? ? ? ?? ?monitor.getDropResult() ? //獲取拖拽對(duì)象所處容器的數(shù)據(jù) ? ? ?? ?monitor.didDrop() ? ?// 當(dāng)前容器能否放置拖拽對(duì)象 ? ? } ? ? ? }) ? return ( ? ? <div id="drag">{name}</div> ? ) }
import { useDrop } from 'react-dnd'; /** 參考api? accept:必填。 (對(duì)應(yīng) drag item.type ) options: 可選的。一個(gè)普通的對(duì)象。 drop(item, monitor): 可選的。當(dāng)兼容項(xiàng)目放在目標(biāo)上時(shí)調(diào)用。 hover(item, monitor): 可選的。將項(xiàng)目懸停在組件上時(shí)調(diào)用。 canDrop(item, monitor): 可選的。使用它來(lái)指定放置目標(biāo)是否能夠接受該物品。如果要始終允許它,則只需忽略此方法。 collect: 可選的。收集功能。它應(yīng)該返回道具的簡(jiǎn)單對(duì)象以返回注入到組件中。它接收兩個(gè)參數(shù),monitor和props */ const Container = (props) => { ? const [{isOver, canDrop}, drop] = useDrop({ ? ? accept: 'test', ? ? drop: (item, monitor) => ({? ? ? ?? ?dropname: '測(cè)試',? ? ? ?? ?top: monitor.getDifferenceFromInitialOffset().y, ? ? ? ? left: monitor.getDifferenceFromInitialOffset().x? ? ? ?}), ? ? ? // 可以在這里配置數(shù)據(jù),與drag中monitor.getDropResult()獲取的信息關(guān)聯(lián) ? ? collect: (monitor) => ({ ? ? ? isOver: monitor.isOver(), ? // 返回拖拽對(duì)象是否懸浮在該容器上 ? ? ? canDrop: monitor.canDrop(), ?// 當(dāng)前容器是否支持拖拽對(duì)象放置 ? ? }) ? }) ? return ( ? ? <div ref={drop}> ?? ??? ?... ? ? </div> ? ) }
實(shí)現(xiàn)任意拖拽
1.在容器中通過(guò)drop —> monitor.getDifferenceFromInitialOffset()獲取拖拽對(duì)象當(dāng)前位置與初始位置的偏移量
2.在drag的end中,通過(guò)monitor.getDropResult()獲取到與初始位置的偏移量,給當(dāng)前拖拽元素的偏移量重新賦值,即可做到任意拖拽
3.如果同時(shí)有很多個(gè)可拖拽的對(duì)象,需要給他們定義一個(gè)index值, 因?yàn)檫@個(gè)可拖拽組件是復(fù)用的,所以我們獲取到的拖拽對(duì)象是個(gè)數(shù)組,我們可以用index作為下標(biāo),給當(dāng)前拖拽組件單獨(dú)賦值
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: '測(cè)試', 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拖拽對(duì)象,也是drop拖拽容器。所以使用useRef()定義ref,然后 drag(drop(ref)),讓它即作為拖拽對(duì)象也作為拖拽容器,然后定義拖拽結(jié)束事件
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> ? ) }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- react-native 圓弧拖動(dòng)進(jìn)度條實(shí)現(xiàn)的示例代碼
- react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序功能
- react中實(shí)現(xiàn)拖拽排序react-dnd功能
- react?實(shí)現(xiàn)表格列表拖拽排序的示例
- React如何使用sortablejs實(shí)現(xiàn)拖拽排序
- React.js組件實(shí)現(xiàn)拖拽排序組件功能過(guò)程解析
- react.js組件實(shí)現(xiàn)拖拽復(fù)制和可排序的示例代碼
- react實(shí)現(xiàn)記錄拖動(dòng)排序
相關(guān)文章
react-native 封裝選擇彈出框示例(試用ios&android)
本篇文章主要介紹了react-native 封裝選擇彈出框示例(試用ios&android),具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07使用React實(shí)現(xiàn)一個(gè)簡(jiǎn)單的待辦事項(xiàng)列表的示例代碼
這篇文章我們將詳細(xì)講解如何建立一個(gè)這樣簡(jiǎn)單的列表,文章通過(guò)代碼示例介紹的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-08-08React?中?memo?useMemo?useCallback?到底該怎么用
在React函數(shù)組件中,當(dāng)組件中的props發(fā)生變化時(shí),默認(rèn)情況下整個(gè)組件都會(huì)重新渲染。換句話說(shuō),如果組件中的任何值更新,整個(gè)組件將重新渲染,包括沒(méi)有更改values/props的函數(shù)/組件。在react中,我們可以通過(guò)memo,useMemo以及useCallback來(lái)防止子組件的rerender2022-10-10react高階組件經(jīng)典應(yīng)用之權(quán)限控制詳解
在React中,高階組件是重用組件邏輯的一項(xiàng)高級(jí)技術(shù)。下面這篇文章主要給大家介紹了關(guān)于react高階組件經(jīng)典應(yīng)用之權(quán)限控制的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09基于react hooks,zarm組件庫(kù)配置開(kāi)發(fā)h5表單頁(yè)面的實(shí)例代碼
這篇文章主要介紹了基于react hooks,zarm組件庫(kù)配置開(kāi)發(fā)h5表單頁(yè)面,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04詳解react使用react-bootstrap當(dāng)輪子造車
本篇文章主要介紹了詳解react使用react-bootstrap當(dāng)輪子造車,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-08-08React項(xiàng)目如何使用Element的方法步驟
本文主要介紹了React項(xiàng)目如何使用Element的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11react項(xiàng)目打包后點(diǎn)擊index.html頁(yè)面出現(xiàn)空白的問(wèn)題
這篇文章主要介紹了react項(xiàng)目打包后點(diǎn)擊index.html頁(yè)面出現(xiàn)空白的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06