React拖拽组件dnd-kit的引入和使用,以及案例
### React拖拽组件dnd-kit的引入和使用
文档地址:https://docs.dndkit.com/
git地址: https://gitcode.com/clauderic/dnd-kit/overview?utm_source=csdn_github_accelerator
React拖拽组件dnd-kit的引入
// React拖拽组件dnd-kit的引入和使用 import { DndContext } from '@dnd-kit/core'; const Demo = () => { return ( <> <DndContext> {/* 可拖拽组件 */} <DraggableBox></DraggableBox> {/* 可落下的容器 */} <DroppableBox></DroppableBox> </DndContext> </> ) } export default Demo;
### DragOverlay
它用于创建一个拖动时的覆盖层。通过使用 DragOverlay 组件,你可以在拖动元素时显示一个覆盖层,通常用于实时预览拖动元素的位置和样式。
import { DragOverlay } from '@dnd-kit/core';
function MyDraggableComponent() {
return (
<div>
<DragOverlay>
{({ isDragging, transform }) => (
<div
style={{
display: isDragging ? 'block' : 'none',
position: 'fixed',
pointerEvents: 'none',
transform: transform ? `translate(${transform.x}px, ${transform.y}px)` : undefined,
}}
>
Dragging overlay
</div>
)}
</DragOverlay>
{/* 其他组件内容 */}
</div>
);
}
### useDraggable
它用于创建一个可拖拽的元素。通过使用 useDraggable,你可以将任意元素设置为可拖拽,并根据拖拽操作的状态更新 UI。
基本用法:
import { useDraggable } from '@dnd-kit/core';
function MyDraggableComponent() {
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
id: 'draggable-item',
});
const style = {
opacity: isDragging ? 0.5 : 1,
cursor: 'grab',
};
return (
<div
ref={setNodeRef}
style={style}
{...listeners}
{...attributes}
>
Drag me
</div>
);
}
### useDroppable
它用于创建一个可放置拖拽元素的区域。通过使用 useDroppable,你可以将拖拽元素放置到指定的容器中,并根据拖拽操作的状态更新 UI。
基本用法:
import { useDroppable } from '@dnd-kit/core';
function MyDroppableComponent() {
const { isOver, setNodeRef } = useDroppable({
id: 'droppable-area',
});
const style = {
background: isOver ? 'lightblue' : 'white',
padding: 16,
border: '1px dashed gray',
};
return (
<div ref={setNodeRef} style={style}>
{isOver ? 'Release to drop' : 'Drag here'}
</div>
);
}
### useDndMonitor
它允许你访问拖放操作的监视器对象。通过这个监视器对象,你可以获取有关拖放操作状态的信息,例如拖动的元素、拖放的位置等
基本用法:
import { useDndMonitor } from '@dnd-kit/core';
function MyComponent() {
const dndMonitor = useDndMonitor();
// 通过监视器对象获取拖放操作的相关信息
const activeId = dndMonitor.active.id;
const overId = dndMonitor.over?.id;
return (
<div>
<p>Active ID: {activeId}</p>
<p>Over ID: {overId}</p>
</div>
);
}
### MouseSensor
是一个用于监测鼠标拖拽事件的传感器。它可以用于创建一个基于鼠标的拖拽操作,并在拖拽过程中实时更新相关状态。
基本用法:
import { MouseSensor, DndContext } from '@dnd-kit/core';
function MyDraggableComponent() {
return (
<DndContext sensors={[MouseSensor]}>
{/* 可拖拽的元素 */}
</DndContext>
);
}
### useSensor
是一个用于创建自定义拖拽传感器的自定义 Hook。通过使用 useSensor,你可以自定义并添加新的拖拽传感器到 DndKit 中,以支持特定的拖拽操作。
基本用法:
import { useSensor, DndContext } from '@dnd-kit/core';
import { MouseSensor, TouchSensor } from '@dnd-kit/core';
function MyDraggableComponent() {
const customSensor = useSensor(MyCustomSensor);
return (
<DndContext sensors={[MouseSensor, TouchSensor, customSensor]}>
{/* 可拖拽的元素 */}
</DndContext>
);
}
### useSensors
是一个用于创建多个拖拽传感器的自定义 Hook。通过使用 useSensors,你可以同时创建并添加多个拖拽传感器到 DndKit 中,以支持多种不同的拖拽操作。
基本用法:
import { useSensors, DndContext } from '@dnd-kit/core';
import { MouseSensor, TouchSensor, KeyboardSensor } from '@dnd-kit/core';
function MyDraggableComponent() {
const sensors = useSensors(MouseSensor, TouchSensor, KeyboardSensor);
return (
<DndContext sensors={sensors}>
{/* 可拖拽的元素 */}
</DndContext>
);
}
### PointerSensor
是一个用于监测指针事件(如鼠标、触摸和指针设备)的传感器。它可以用于创建一个通用的指针事件监测器,以便支持多种不同的指针设备和操作。
基本用法:
import { PointerSensor, DndContext } from '@dnd-kit/core';
function MyDraggableComponent() {
return (
<DndContext sensors={[PointerSensor]}>
{/* 可拖拽的元素 */}
</DndContext>
);
}
<!-- 在拖拽操作开始之前,鼠标或指针设备需要移动至少 5 个像素的距离。一旦达到这个距离,传感器将开始响应拖拽操作 -->
useSensor(PointerSensor, {
activationConstraint: {
distance: 5,
},
}),
### MouseSensor和PointerSensor的区别
MouseSensor 主要用于监测鼠标事件,例如鼠标移动、点击和拖拽操作。它专门针对鼠标设备,可以精确地监测鼠标的位置和操作。
PointerSensor 则更通用,可以监测多种指针设备的事件,包括鼠标、触摸屏和指针设备(如触摸笔)。它能够适配多种输入设备,使得拖拽操作在不同类型的设备上都能够得到良好的支持。
总的来说,PointerSensor 更通用,而 MouseSensor 更专注于鼠标事件的监测。
完整案例
import React, { HTMLProps, useState } from 'react';
import { DndContext, DragOverlay, useDraggable, useDroppable } from '@dnd-kit/core';
const Droppable: React.FC<HTMLProps<HTMLDivElement>> = ({ children, id, disabled, ...rest }) => {
const { setNodeRef } = useDroppable({
id: id || 'droppable',
disabled,
});
return (
<div {...rest} ref={setNodeRef}>
{children}
</div>
);
};
interface dragBoxListItem {
id: string,
data: any,
}
const dragBoxList = [{
id: 1,
data: {
title: '第一个可拖拽组件'
}
}, {
id: 2,
data: {
title: '第二个可拖拽组件'
}
}]
const Test = () => {
// 当前拖拽的组件
const [item, setItem] = useState<dragBoxListItem>();
// 是否还悬浮side的容器区域
const [isOver, setIsOver] = useState(false);
const handleDragStart = (event: any) => {
console.log('drag start', event, '=========')
const current = event.active.data.current as any;
setItem({
id: event.active.id,
data: current,
})
}
const handleDragMove = (event: any) => {
console.log('drag move', event, '=========')
}
const handleDragEnd = (event: any) => {
console.log('drag end', event, '=========')
setIsOver(event.over?.id === 'logicflow');
}
const draggableMarkUp = () => {
if (!item || !isOver) return;
return (
<Droppable id="side">
<DraggableBox id={item?.id} data={item?.data}></DraggableBox>
</Droppable>
)
}
return (
<>
<DndContext
onDragStart={handleDragStart}
onDragMove={handleDragMove}
onDragEnd={handleDragEnd}
>
<div style={{ display: 'flex' }}>
{/* 可拖拽组件 */}
<Droppable id="side">
{
dragBoxList.map(item => (
<DraggableBox key={item.id} id={item.id} data={item.data}></DraggableBox>
))
}
</Droppable>
{/* 可落下的容器 */}
<DroppableBox id="logicflow">
{draggableMarkUp()}
</DroppableBox>
</div>
<DragOverlay>
<button style={{ visibility: isOver ? 'hidden' : 'visible' }}>{item?.data?.title}</button>
</DragOverlay>
</DndContext>
</>
)
}
export default Test;
const DraggableBox = (props: any) => {
const {attributes, listeners, setNodeRef, isDragging} = useDraggable({
id: props.id,
data: props.data,
});
const style = {
opacity: isDragging ? 0.5 : 1,
cursor: 'grab',
};
return (
<div style={{height: 500, width: 200, marginRight: 40, ...style}} ref={setNodeRef}>
<button {...listeners} {...attributes}>{props.data.title}</button>
</div>
)
}
const DroppableBox = (props: any) => {
const {isOver, setNodeRef} = useDroppable({
id: props.id
});
const style = {
background: isOver ? 'lightblue' : 'white',
padding: 16,
with: 400,
border: '1px dashed gray',
};
return <div ref={setNodeRef} style={{opacity: 0.2, ...style}}>
{
props.children || '可以落下的容器'
}
</div>
}
效果如下图
图1: 初始展示, 图2正在拖动中, 图3已经拖进容器里




浙公网安备 33010602011771号