初始 @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;
相关推荐
Aphasia3119 小时前
手写KeepAlive组件
前端·react.js·面试
whatever who cares14 小时前
大型 React 项目的文件结构
前端·react.js·前端框架
假如让我当三天老蒯14 小时前
useCallback 详细解释(从原理到用法)(自学用)
前端·react.js
Vu46115 小时前
nextjs的图片和文字优化
react.js
gogoing18 小时前
React Hooks 完整指南
react.js
假如让我当三天老蒯19 小时前
State和Props区别和左右(自学用)
前端·react.js
夜雪闻竹20 小时前
React Query + REST API 最佳实践
前端·react.js·前端框架
戈德斯文21 小时前
我做了一面互联网摸鱼墙:从无限 Canvas 到本地生产环境
react.js·canvas·next.js
vim怎么退出2 天前
Dive into React——Hooks 原理
react.js·源码阅读