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