初始 @dnd-kit

基础概念

  • DndContext 用于包装拖拽根组件,DraggableDroppable 都需要包裹在 DndContext
  • Droppable 用于包装接收拖拽元素的组件,使组件能够放置
  • Draggable 用于包装需要拖动的组件,使组件能够被拖拽
  • SortableContext 创建一个拖放排序的容器,其中的子元素可以被拖动并重新排序
  • Sensors 用于检测不同的输入方法,以启动拖动操作、响应移动以及结束或取消操作,内置传感器:指针、鼠标、触摸、键盘

安装依赖

@dnd-kit/core: 6.0.8, @dnd-kit/sortable: 7.0.2, @dnd-kit/utilities: 3.2.1,

  1. useSensors@dnd-kit 库中的一个函数,用于配置和管理拖拽操作的传感器。传感器是用于检测用户交互的输入设备或方式的模块。
  2. useSensor(PointerSensor) 行创建了一个名为 PointerSensor 的传感器实例,并将其添加到 sensors 数组中。PointerSensor 用于捕获指针设备(如鼠标或触摸屏)的交互,允许用户通过拖拽来操作元素。
  3. useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }) 行创建了一个名为 KeyboardSensor 的传感器实例,并将其添加到 sensors 数组中。这里还提供了一个选项对象,指定了 coordinateGetter 函数,用于确定键盘输入的坐标。KeyboardSensor 允许用户使用键盘来操作元素,通常用于键盘控制的排序。
js 复制代码
import React, { FC, useState } from "react";
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
} from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import Item from "./Item";

type ComponentType = {
  fe_id: string;
  title: string;
};

const Container: FC = () => {
  const [items, setItems] = useState<ComponentType[]>([
    { fe_id: "c1", title: "组件1" },
    { fe_id: "c2", title: "组件2" },
    { fe_id: "c3", title: "组件3" },
  ]);

  // 配置和管理拖拽操作的传感器
  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );

  const itemsWithId = items.map((c) => {
    return {
      ...c,
      id: c.fe_id,
    };
  });

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
    >
      <SortableContext
        items={itemsWithId}
        strategy={verticalListSortingStrategy}
      >
        {itemsWithId.map((c) => (
          <Item key={c.id} id={c.id} title={c.title} />
        ))}
      </SortableContext>
    </DndContext>
  );
};

export default Container;

设置 onDragEnd 函数。

  • event 对象中解构出 activeover 属性。active 代表拖动操作的起点元素,over 代表拖动操作的结束点元素。
  • 检查起点元素和结束点元素的 id 是否不相同。
  • 使用 arrayMove 函数将 active 元素从 oldIndex 移动到 newIndex,实现元素的重新排序。
js 复制代码
function handleDragEnd(event: DragEndEvent) {
  const { active, over } = event;
  if (over == null) return;

  if (active.id !== over.id) {
    setItems((items) => {
      const oldIndex = items.findIndex((c) => c.fe_id === active.id);
      const newIndex = items.findIndex((c) => c.fe_id === over.id);
      return arrayMove(items, oldIndex, newIndex);
    });
  }
}

Item.tsx

  1. attributes: 这是一个包含属性的对象,通常应用于拖拽目标元素,以便处理拖拽的交互。这些属性包括样式属性、拖拽相关的属性等,用于实现拖拽时的视觉效果。
  2. listeners: 这是一个包含事件监听器的对象,用于监听拖拽过程中的事件,例如拖拽开始、拖拽结束等。这些事件监听器应该绑定到拖拽目标元素,以便捕获用户的拖拽操作。
  3. setNodeRef: 这是一个回调函数,用于设置拖拽目标元素的引用。通常,你需要将这个回调函数传递给要进行拖拽的元素,以确保能够正确地识别和操作拖拽目标。
  4. transform: 这是一个用于处理拖拽元素的变换效果的 CSS 属性。可以使用它来应用平移(translation)、缩放(scale)等变换,以使拖拽效果看起来更加自然。
  5. transition: 这是一个用于定义拖拽元素的过渡效果的 CSS 属性。可以使用它来创建平滑的过渡动画,使拖拽操作更加流畅。
js 复制代码
import React, { FC } from "react";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";

type PropsType = {
  id: string;
  title: string;
};

const Item: FC<PropsType> = (props: PropsType) => {
  const { id, title } = props;

  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    border: "1px solid #ccc",
    margin: "10px 0",
    background: "#f1f1f1",
  };

  return (
    <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
      Item {title}
    </div>
  );
};

export default Item;
相关推荐
牛仔只喝牛奶5 小时前
多端跨端技术选型:小程序 + H5 + App 的两栈拆分落地
react native·react.js
wear工程师8 小时前
setState 到底是不是异步的?这题从 React 16 问到 18,标准答案早就变了
react.js·面试
wanghowie10 小时前
LangGraph4j 落地(二)— ReAct 多步工具与 trace 扩展
前端·react.js·前端框架
csj5011 小时前
前端基础之《React(11)—state声明式》
前端·react.js
张元清12 小时前
React useLocalStorage Hook:SSR 安全的持久化状态(2026)
javascript·react.js
析数塔12 小时前
2026前端框架深度解析:React Compiler、Angular Zoneless、Vue 3.5重写游戏规则
前端·vue.js·react.js
杖雍皓12 小时前
没有服务器如何构建现代 Web 应用:平台选型与组合策略
运维·服务器·前端·react.js·github·netlify·vercel
sun_weitao12 小时前
微前端框架之qiankun 怎么用?vue3+vite+qiankun 和 react + qiankun
前端·react.js·前端框架
名字还没想好☜1 天前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect
我是大卫1 天前
【图】React源码解析-第四部分:事件与跨层传递
react.js·源码