You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dnd-kit实现Todo拖拽时监听器冲突且拖拽失效问题排查

dnd-kit Todo项拖拽排障指南
  • 检查SortableContext的items属性
    确保SortableContext的items传入的是所有Todo项的唯一ID数组,且每个Todo组件接收的id与数组内ID完全匹配。示例:

    // ListContainer.jsx 中的SortableContext配置
    <SortableContext items={todoIds} strategy={verticalListSortingStrategy}>
      {todos.map(todo => <Todo key={todo.id} id={todo.id} {...todo} />)}
    </SortableContext>
    

    ID不匹配会导致拖拽系统无法识别可排序项。

  • 确认useSortable属性的正确绑定
    即使将拖拽触发移至单独按钮,Todo容器元素仍需绑定setNodeRef、transform和transition属性,拖拽按钮则绑定attributes和listeners。示例:

    // Todo.jsx
    import { useSortable } from '@dnd-kit/sortable';
    import { CSS } from '@dnd-kit/utilities';
    
    const Todo = ({ id, content }) => {
      const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
      const dragStyle = {
        transform: CSS.Transform.toString(transform),
        transition,
      };
    
      return (
        <div ref={setNodeRef} style={dragStyle}>
          <button {...attributes} {...listeners}>拖拽</button>
          <span>{content}</span>
        </div>
      );
    };
    

    遗漏容器元素的属性绑定会导致拖拽时无法正确计算位置和更新样式。

  • 排查监听器冲突根源
    若之前存在监听器冲突,可给拖拽按钮添加e.stopPropagation()阻止事件冒泡,避免与Todo容器上的其他点击/触摸事件干扰。示例:

    <button 
      {...attributes} 
      {...listeners}
      onClick={(e) => e.stopPropagation()}
    >拖拽</button>
    
  • 确保引入并配置排序策略
    必须从@dnd-kit/sortable导入对应排序策略(如verticalListSortingStrategy)并传入SortableContext,否则无法处理拖拽排序逻辑。

  • 完善DndContext的核心配置
    DndContext需绑定collisionDetection和onDragEnd回调,前者用于检测拖拽碰撞,后者用于拖拽结束后更新Todo列表顺序。示例:

    // ListContainer.jsx
    import { DndContext, closestCenter } from '@dnd-kit/core';
    import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
    
    const ListContainer = ({ todos, setTodos }) => {
      const handleDragEnd = (event) => {
        const { active, over } = event;
        if (active.id !== over.id) {
          // 此处编写Todo列表重排序逻辑,更新todos数组
          const oldIndex = todos.findIndex(t => t.id === active.id);
          const newIndex = todos.findIndex(t => t.id === over.id);
          const newTodos = Array.from(todos);
          [newTodos[oldIndex], newTodos[newIndex]] = [newTodos[newIndex], newTodos[oldIndex]];
          setTodos(newTodos);
        }
      };
    
      return (
        <DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
          <SortableContext items={todos.map(t => t.id)} strategy={verticalListSortingStrategy}>
            {todos.map(todo => <Todo key={todo.id} id={todo.id} content={todo.content} />)}
          </SortableContext>
        </DndContext>
      );
    };
    

    缺少onDragEnd会导致拖拽结束后无数据更新,看起来拖拽无效果。

内容的提问来源于stack exchange,提问作者Akshat Dubey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:10:58