React 拖拽排序实战:用 @dnd-kit 实现可拖拽、可排序的看板

test12026-10-174 次阅读

为什么选 @dnd-kit

原生 HTML5 拖拽 API 在移动端、可访问性和复杂交互上坑很多。@dnd-kit 用 Pointer 事件重写了一套拖拽内核,体积小、支持键盘操作和传感器自定义,是现在 React 拖拽的主流选择。

安装与最小骨架

npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities

DndContext 提供拖拽上下文,SortableContext 负责可排序列表,useSortable 让单个条目具备拖拽能力。

可排序列表组件

import { useState } from 'react';
import {
  DndContext, closestCenter, PointerSensor, useSensor, useSensors,
  DragEndEvent,
} from '@dnd-kit/core';
import {
  SortableContext, arrayMove, verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { SortableItem } from './SortableItem';

export function Board() {
  const [items, setItems] = useState(['需求评审', '开发', '测试', '上线']);
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 5 } })
  );

  function handleDragEnd(event: DragEndEvent) {
    const { active, over } = event;
    if (!over || active.id === over.id) return;
    setItems((prev) => {
      const from = prev.indexOf(String(active.id));
      const to = prev.indexOf(String(over.id));
      return arrayMove(prev, from, to);
    });
  }

  return (
    <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
      <SortableContext items={items} strategy={verticalListSortingStrategy}>
        {items.map((id) => <SortableItem key={id} id={id} />)}
      </SortableContext>
    </DndContext>
  );
}

单个可排序条目

import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

export function SortableItem({ id }: { id: string }) {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };

  return (
    <li ref={setNodeRef} style={style} {...attributes} {...listeners}>
      {id}
    </li>
  );
}

几个工程注意点

  • activationConstraint 设 distance,避免点击误触发拖拽。
  • 拖拽手柄建议单独绑定 listeners,整行可点击时不与排序冲突。
  • 跨容器拖拽用 multiple containers,配合 onDragOver 做实时迁移。
  • 列表数据用唯一 id 数组管理,拖拽结束用 arrayMove 重排即可,无需手动操作 DOM。
T

test1

文章作者

为什么选 @dnd-kit 原生 HTML5 拖拽 API 在移动端、可访问性和复杂交互上坑很多。@dnd-kit 用...

分类
技术
发布时间
2026-10-17
字数
约 2050 字
阅读
4 次