React DnD是封装的HTML5拖放API的React组件,可用于构建拖放交互功能。下面详细讲解React DnD如何处理拖拽,在这个过程中,将提供两个示例说明。
1. 拖拽源
拖拽源是可以被拖拽的组件。在React DnD中,拖拽源分为两种:简单的拖拽源和自定义拖拽源。
简单拖拽源
简单的拖拽源指的是一个纯组件,该组件可以设置可以被拖拽的数据类型以及数据。
import { useDrag } from 'react-dnd'
export default function SimpleDragSource() {
const [{ isDragging }, drag] = useDrag({
item: { type: 'BOX', text: 'This is a simple drag source' },
collect: monitor => ({
isDragging: monitor.isDragging()
})
})
const opacity = isDragging ? 0.4 : 1
return (
<div ref={drag} style={{ opacity }}>
Simple Drag Source
</div>
)
}
上面的代码展示了一个简单的拖拽源,它被设置为可以拖拽type
为BOX
,数据为text: 'This is a simple drag source'
。在渲染组件时,要使用useDrag
hook。useDrag
hook接受一个配置对象,包含item
和collect
属性。item
属性指定了拖拽源能够拖拽的数据类型及其数据。collect
属性场景的monitor
对像,这个对象包含此拖动源内部状态以及DnD状态,这个对象的isDragging()
方法可以判断当前组件是否处于拖动状态。
在组件渲染时需要将drag
ref通过组件绑定。当我们通过useDrag
hook生成的ref函数传递给组件后,将会自动添加拖拽起始事件监听。渲染视图时我们还需要根据动态改变拖拽表现的状态和数据来改变样式或内容。在这个例子种我们通过opacity
属性来改变组件在拖拽状态下的透明度。
自定义拖拽源
由于简单的拖拽源只能提供基本的拖拽信息,不能满足对复杂情况的应用,React DnD还提供了一种自定义拖拽源的方式。
import React, { useState } from "react";
import { useDrag } from "react-dnd";
import { ItemTypes } from "./ItemTypes";
const style = {
border: "1px dashed gray",
padding: "0.5rem 1rem",
backgroundColor: "white",
cursor: "move"
};
export const Box = ({ id, left, top, hideSourceOnDrag, children }) => {
const [{ isDragging }, drag] = useDrag({
item: { type: ItemTypes.BOX, id, left, top },
collect: monitor => ({
isDragging: monitor.isDragging()
})
});
const [isHidden, setIsHidden] = useState(false);
if (isDragging && hideSourceOnDrag) {
setIsHidden(true);
}
return (
<div
ref={drag}
style={{ ...style, opacity: isDragging ? 0.5 : 1, display: isHidden ? "none" : "block" }}
>
{children}
</div>
);
};
上面的代码是一个自定义的拖拽源的示例,由Box
组件创建。组件可以接受id
、left
、top
、hideSourceOnDrag
、children
作为参数。在useDrag
hook中指定数据类型为ItemTypes.BOX
,组件的left
和top
作为初始位置进行设置。在collect
属性中通过isDragging
方法设置组件是否处于拖拽状态的内部变量isDragging
。children
是组件要显示的文字。
当我们拖动这个Box
组件时,将会执行useDrag
hook,并通过drag
ref将事件绑定到了组件上。我们在style
中通过opacity
属性来改变被拖拽组件的透明度;在display
中,我们将组件隐藏以避免在拖拽时影响其他组件。如果不需要影藏组件,可以将hideSourceOnDrag
设置为`false´。
2. 放置目标
放置目标是接收可以拖拽的组件的组件。在React DnD中,放置目标也需要分为简单的放置目标和自定义放置目标。
简单放置目标
简单放置目标是指只能接收特定数据类型的拖拽源。在下面这个例子中,我们有一个简单的放置目标,它只能接收type
为BOX
的拖拽源。
import { useDrop } from 'react-dnd'
export default function SimpleDropTarget() {
const [{ isOver }, drop] = useDrop({
accept: 'BOX',
collect: monitor => ({
isOver: monitor.isOver()
})
})
const backgroundColor = isOver ? 'lightgreen' : 'white'
return (
<div ref={drop} style={{ backgroundColor }}>
{isOver ? 'Release to drop' : 'Drag a box here'}
</div>
)
}
在渲染该组件后,使用useDrop
hook并传递一个配置对象。accept
属性接收一个数据类型的数组,并在所有拖拽源中查找type
为BOX
的拖拽源。在配置对象中,使用collect
方法将isOver
状态传递到渲染函数中。当拖拽源经过组件时,isOver
属性将设置为true
,移出时则恢复。
在渲染的div中,使用我们的drop
ref将事件处理程序绑定到组件上。在组件渲染时,调整其样式来反映拖拽源是否可以被接收的状态。
自定义放置目标
自定义放置目标可以接受任何类型的拖拽源。在下面这个例子中,我们有一个自定义的放置目标,它可以接受任何类型的拖拽源。
import React, { useState } from "react";
import { useDrop } from "react-dnd";
import { ItemTypes } from "./ItemTypes";
const style = {
height: "12rem",
width: "12rem",
margin: "1rem",
border: "1px solid black",
position: "relative"
};
export const Dustbin = ({ onDrop }) => {
const [hasDropped, setHasDropped] = useState(false);
const [{ isOver, canDrop }, drop] = useDrop({
accept: ItemTypes.BOX,
drop: () => {
setHasDropped(true);
onDrop();
},
collect: monitor => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
})
});
const isActive = isOver && canDrop;
let backgroundColor = "#222";
if (isActive) {
backgroundColor = "darkgreen";
} else if (canDrop) {
backgroundColor = "darkkhaki";
}
return (
<div ref={drop} style={{ ...style, backgroundColor }}>
{hasDropped ? (
<p>Box has been dropped!</p>
) : (
<p>Drag a box here.</p>
)}
</div>
);
};
我们使用了useDrop
hook创建了一个自定义放置目标组件。在useDrop
hook中,我们指定了可以接收的数据类型为ItemTypes.BOX
。我们还将drop
回调传递到了drop
ref中。当一个拖拽源被放置时,如果它是有效的拖拽源类型,我们将hasDropped
状态设置为true
。
在collect
属性中,我们可以使用isOver
和canDrop
方法将数据传递到组件中。我们可以使用isActive
变量计算放置目标当前是否处于拖拽源悬停状态。
在渲染的组件中,我们展示一个提示信息,根据当前状态调整其样式。当拖拽源被放置到放置目标中时,将会调用onDrop
回调函数。可以在这里处理放置后的操作。
这就是React DnD如何处理拖拽的详解,在这个过程中我们已经提供了两个示例说明来帮助您理解。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:React DnD如何处理拖拽详解 - Python技术站