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已经拖进容器里
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理