近期在工作中遇到了一個(gè)新的需求,該需求需要實(shí)現(xiàn)某個(gè)組件的拖拽,面對(duì)這個(gè)需求的第一個(gè)項(xiàng)目肯定是問(wèn)問(wèn)度娘和用最大同性交友網(wǎng)站進(jìn)行搜索,最終皇天不負(fù)有心人,讓我找到了這個(gè)17k star的React拖拽庫(kù)——React DnD。
npm install react-dnd -S // react-dnd包,其核心包npm install react-dnd-html5-backend -S // 拖拽的底層實(shí)現(xiàn)所需要的庫(kù)
通過(guò)使用React DnD這個(gè)庫(kù),我認(rèn)為里面最有用的部分包含一個(gè)組件和兩個(gè)Hook API,它們分別是:
如果想讓某一內(nèi)容使用React DnD的能力,需要將該部分用DndProvider進(jìn)行包裹,其接收參數(shù)如下所示:
下面來(lái)一起看看該組件的簡(jiǎn)單使用:
import {DndProvider} from 'react-dnd';import {HTML5Backend} from 'react-dnd-html5-backend';function App() { return ( <div className="App"> <DndProvider backend={HTML5Backend}> 此處將放拖拽相關(guān)內(nèi)容 </DndProvider> </div> );}export default App;
既然知道了整個(gè)操縱空間,接下來(lái)需要了解的就是從什么位置進(jìn)行拖拽,該庫(kù)提供了useDrag hook API,該元素可以讓一個(gè)DOM元素實(shí)現(xiàn)拖拽效果。
參數(shù):
spec:創(chuàng)建規(guī)范對(duì)象的規(guī)范對(duì)象或函數(shù),其詳細(xì)內(nèi)容如下所示:
type:
必須,是一個(gè)字符串或Symbol,只有drop和此值相同才可以進(jìn)行放置;
item:
必須,用于描述被拖動(dòng)的數(shù)據(jù)
previewOptions:
可選的,一個(gè)簡(jiǎn)單對(duì)象,用于描述拖動(dòng)預(yù)覽選項(xiàng);
options:
可選的,一個(gè)簡(jiǎn)單對(duì)象
end(item, monitor):
可選的,當(dāng)拖拽停止,該函數(shù)被調(diào)用;
canDrag(monitor):
可選的,使用它指定當(dāng)前是否允許拖動(dòng);
isDragging(monitor):
可選的,默認(rèn)情況下,只有啟動(dòng)拖動(dòng)操作的拖動(dòng)源才被視為拖動(dòng);
collect:
可選的,監(jiān)聽(tīng)功能。
返回值:
返回值是一個(gè)數(shù)組,數(shù)組內(nèi)容分別為:
collected:一個(gè)對(duì)象,包含從collect函數(shù)收集的屬性,如果collect未定義函數(shù),則返回一個(gè)空對(duì)象;drag:拖動(dòng)器的連接器功能,必須附加到DOM的可拖動(dòng)部分;dragPreview:用于拖動(dòng)預(yù)覽的連接器功能,可以附加到DOM的預(yù)覽部分;
與拖動(dòng)部分建立連接:
通過(guò)ref屬性,將drag或dragPreview綁定到拖拽源上。
下面一起來(lái)看看useDrag部分的使用
import {useDrag} from 'react-dnd';const SourceBox = props => { const {children} = props; /** * 返回的參數(shù) * collected:一個(gè)對(duì)象,包含從collect函數(shù)收集的屬性,如果collect未定義函數(shù),則返回一個(gè)空對(duì)象 * drag:拖動(dòng)器的連接器功能,必須附加到DOM的可拖動(dòng)部分 * dragPreview:用于拖動(dòng)預(yù)覽的連接器功能,可以附加到DOM的預(yù)覽部分 */ const [collected, drag, dragPreview] = useDrag({ // 只有drop和此值相同才可以進(jìn)行放置 type: 'box', // 描述要拖動(dòng)的數(shù)據(jù) item: { detail: '我是可以拖動(dòng)的數(shù)據(jù)!!!' }, // 拖動(dòng)停止的手end將會(huì)被調(diào)用 end: (item, monitor) => { // getDropResult()獲取釋放后的結(jié)果 console.log('monitor.getDropResult():', monitor.getDropResult()); // source是否已經(jīng)drop在target console.log('monitor.didDrop()', monitor.didDrop()); }, // 指定當(dāng)前是否允許拖動(dòng),默認(rèn)允許 canDrag: monitor => { return true; }, // 監(jiān)聽(tīng)功能 collect: (monitor, props) => { return { isDragging: monitor.isDragging() }; } }); return ( <div ref={drag}> {children} </div> );};export default SourceBox;
為了將內(nèi)容放置到目標(biāo)位置,提供了useDrop函數(shù),如下所示:
參數(shù):
spec:創(chuàng)建規(guī)范對(duì)象的規(guī)范對(duì)象或函數(shù),其詳細(xì)內(nèi)容如下所示:
accept:
必須,一個(gè)字符串,此放置目標(biāo)將僅對(duì)于指定類(lèi)型的拖動(dòng)源產(chǎn)生的項(xiàng)目作出反應(yīng)。
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)是否接受該拖拽內(nèi)容。
collect:
可選的,監(jiān)聽(tīng)功能。
返回值:
返回值是一個(gè)數(shù)組,數(shù)組內(nèi)容分別為:
collected:一個(gè)對(duì)象,包含從collect函數(shù)收集的屬性,如果collect未定義函數(shù),則返回一個(gè)空對(duì)象;drop:一個(gè)用于放置目標(biāo)的連接器函數(shù),必須附加到DOM的放置部分;
與放置部分建立連接:
通過(guò)ref屬性,將drop與放置部分建立連接。
下面一起來(lái)看看useDrop部分的使用
import {useDrop} from "react-dnd";const TargetBox = () => { const [collected, drop] = useDrop({ // 此放置目標(biāo)將僅對(duì)于指定類(lèi)型的拖動(dòng)源產(chǎn)生的項(xiàng)目作出反應(yīng) accept: 'box', // 當(dāng)兼容項(xiàng)目放在目標(biāo)時(shí)調(diào)用 drop: (item, monitor) => { console.log('我已經(jīng)被放到目標(biāo)!!!') }, // 監(jiān)聽(tīng)功能 collect: monitor => { return { // 是否重疊 isOver: monitor.isOver(), // 是否可以放置 canDrop: monitor.canDrop(), item: monitor.getItem(), didDrop: monitor.didDrop() }; } }); return ( <div ref={drop}> <div className="targetBox"> 這是放置的區(qū)塊 </div> </div> );};export default TargetBox;
useDrag和useDrop上掛載了很多選項(xiàng),這些選項(xiàng)中很多存在monitor對(duì)象,該對(duì)象上掛載了很多方法,下面就簡(jiǎn)要概述幾個(gè)主要方法,如下所示:
drag上的monitor上的方法:
drop上的monitor上的方法:
拖拽前:
拖拽中:
拖拽中拖拽的內(nèi)容跟隨鼠標(biāo)移動(dòng)。
拖拽后:
拖拽釋放鼠標(biāo)后,一些內(nèi)容被打印出來(lái),打印的結(jié)果是先輸出drop中的內(nèi)容再輸出end中的內(nèi)容,所以我們想做一些處理最后在SourceBox中進(jìn)行處理,如果在drop中改變React相關(guān)的數(shù)據(jù)會(huì)報(bào)錯(cuò)。
這個(gè)庫(kù)的資料千篇一律,在使用過(guò)程中遇到了一些坑,接下來(lái)與各位老鐵分享一下這些坑,防止后續(xù)深陷其中。
本文鏈接:http://www.tebozhan.com/showinfo-26-51254-0.html這個(gè)17k star的拖拽庫(kù)有點(diǎn)料
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: FileProvider共享文件和訪問(wèn)文件的內(nèi)容提供者
下一篇: 一文搞懂 Java8 reduce操作