React Dnd
React DnD是一组React实用程序,可帮助您构建复杂的拖放接口,同时保持组件解耦。它非常适合Trello和Storify等应用程序,在这些应用程序中,拖动在应用程序的不同部分之间传输数据,组件会根据拖放事件更改其外观和应用程序状态。
拖放本质上是有状态的。要么正在进行拖动操作,要么没有。要么有当前类型和当前项,要么没有。
React DnD通过称为监视器的内部状态存储上的几个微小包装器将此状态暴露给您的组件。监视器允许您更新组件的道具,以响应拖放状态的更改。
使用:
npm install react-dnd react-dnd-html5-backend
官网地址:https://react-dnd.github.io/react-dnd/about
简单案例:
本案例使用React技术环境写的,
将box1中可拖拽的元素拖放至box2,box2中也可以拖至box1中。
在实际开发中 Draggable 组件和 Droppable 组件是在分开文件中,这里只是简单案例,为方便都在一个文件中。
import React from 'react';
import {
DndProvider, useDrag, useDrop } from 'react-dnd';
import {
HTML5Backend } from 'react-dnd-html5-backend';
const Code: React.FC = () => {
// 设置动态拖拽数据
const [box1, setBox1] = React.useState([
{
id: 1 }, {
id: 2 }, {
id: 3 },
])
const [box2, setBox2] = React.useState([{
id: 1 }]);
// 可拖拽的元素
function Draggable({
id }) {
const [{
isDragging }, drag] = useDrag(() => ({
type: "card",
item: {
id },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
}))
if (isDragging) {
return <div ref={
drag}></div>
}
return <div id='drap' style={
{
"margin": "8px", "width": "50px", "background": "rgb(118 208 235)" ,"display":"inline-block"}} ref={
drag}>{
`Drag ${
id}`}</div>
}
// 存放拖拽元素的容器
function Droppable({
handleDrop, state, text ,children}) {
const [{
isDver }, drop] = useDrop(() => ({
accept: "card", // 接收的类型,和useDrag中type对应
collect: (monitor) => ({
isDver: monitor.isOver(),
}),
drop: (item: any) => {
handleDrop(item)
console.log(item)
}
}), [state])
return <div id='drop' ref={
drop} style={
{
"padding": "10px", "width": "320px", "background": "#fff" }}>
{
text} <br/>
{
children}
</div>
}
const handleDrop1 = (item) =>{
// 删除box2
const arrCopy= [...box2];
const index = arrCopy.findIndex((each)=>each.id == item.id)
const copyItem = arrCopy[index];
arrCopy.splice(index,1);
setBox2(arrCopy);
// 在box1中添加
setBox1((prev) => [...prev,copyItem]);
}
const handleDrop2 = (item) =>{
// 删除box2
const arrCopy= [...box1];
const index = arrCopy.findIndex((each)=>each.id == item.id)
const copyItem = arrCopy[index];
arrCopy.splice(index,1);
setBox1(arrCopy);
// 在box1中添加
setBox2((prev) => [...prev,copyItem]);
}
return (
<DndProvider backend={
HTML5Backend}>
{
/* <Draggable id={1}></Draggable>
<Draggable id={2}></Draggable> */}
<Droppable text={
"box1"} state={
box1} handleDrop={
handleDrop1}>
{
box1.map(drag => <Draggable key={
drag.id} id={
drag.id} />)}
</Droppable>
<Droppable text={
"box2"} state={
box2} handleDrop={
handleDrop2}>
{
box2.map(drag => <Draggable key={
drag.id} id={
drag.id} />)}
</Droppable>
</DndProvider>
)
};
export default Code;