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已经拖进容器里

 

 

posted @   君临天下之徐少  阅读(954)  评论(0编辑  收藏  举报
编辑推荐:
· 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编程运行原理
点击右上角即可分享
微信分享提示