大家好,今天的篇章要介紹的是 React DnD
一樣會延續前一天的專案結構接續下去進行修改,如果沒有參與到昨天的建置過程,這邊也有提供原始碼
https://github.com/littlehorseboy/typescript-react/tree/day18-draft-js
React DnD 可以讓你用 React 的思維來實作 drag drop 的功能,筆者接下來會先參考 http://react-dnd.github.io/react-dnd/examples/dustbin/single-target 這裡的功能來實作
首先先安裝所需的東西
npm i react-dnd
npm i react-dnd-html5-backend
npm i classnames
npm i -D @types/classnames
Classnames,這是一個在 JS 之中要組 className 字串用的超好用第三方函式庫,是從 material-ui v3 時所用,雖然在 material-ui v4 時改用了更輕量的 clsx,不過筆者暫時沒有跟著換
定義 types,後一段會講到它的用途
+ src/components/ReactDnDPractice/itemTypes.ts
+ src/components/ReactDnDPractice/Garbage/Garbage.tsx
這裡定義了 useDrag
const [{ isDragging }, drag] = useDrag({...
第二個參數 drag 是用來給要拖動的目標,掛到 div 的 ref 上用
然後是 useDrag 裡面的屬性
item: type 為必填,後續的 drop 組件在接收 drag 組件時,會先認這個值來做處理,所以用了剛剛定義的 itemTypes.ts 的內容,主要是為了集中管理,如果有不小心重複到可能會發生無法預期的後果,然後其它的定義屬性都是自由選配的,依照你的需求來讓 drop 組件讀到時做邏輯處理用
end: 監聽在拖動結束時,也就是滑鼠放開,所執行的事件
collect: 取得 DragSourceMonitor 所擁有的參數都要從這裡定義
接下來將他放進頁面中使用
+ src/components/ReactDnDPractice/ReactDnDPractice.tsx
然後執行看看
得到一個可以拖動的區塊,還要新增一塊區域能接受 garbage drop 至其中的區塊,來做互動
+ src/components/ReactDnDPractice/GarbageCan/GarbageCan.tsx
這裡定義了 useDrop
const [{ canDrop, isOver }, drop] = useDrop({...
第二個參數 drop 是用來給要放置拖動組件的目標,掛到 div 的 ref 上用
然後是 useDrop 裡面的屬性
drop: 監聽接收到拖動組件時的事件,可以回傳內容,也可以用 void 來直接處理拖動組件內所夾帶的屬性
collect: 取得 DropTargetMonitor 所擁有的參數都要從這裡定義
接下來將他放進頁面中使用
呈現結果
以上就是筆者使用 React DnD 做的小小基本實例,用 React 的模式來實作 drag drop,也可以在 drop 當下改變 component 的 state,來 render 想要的結果,依靠 React DnD 提供的這些屬性就能非常方便的做出想要的功能(像是真的丟進垃圾桶裡面,並且還可以取出來,或是限制垃圾桶只能接一個垃圾這種)
最後附上原始碼
https://github.com/littlehorseboy/typescript-react/tree/day19-react-dnd
明天會介紹 Storybook,它可以用來管理你的 components