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

dnd-kit可排序列表拖拽手柄失效:setActivatorNodeRef无作用

问题:dnd-kit拖拽手柄失效,整个列表项均可触发拖拽

我在使用dnd-kit实现带拖拽手柄的可排序列表时遇到问题:期望仅将按钮设为拖拽激活器,但当前整个父元素均可触发拖拽。已按照官方文档使用setActivatorNodeRef,但该方法无效果,且无任何警告或错误。

错误原因

问题出在SortableItem组件的实现上:你把useSortable返回的attributes和listeners直接绑定到了父级<div>上,这会让整个列表项都绑定拖拽触发事件,完全覆盖了setActivatorNodeRef的作用——即使你指定了手柄为激活元素,父元素的拖拽事件依然会被触发。

修复方案

只需要调整SortableItem的代码,移除父div上的attributes和listeners绑定,让这些事件只作用在拖拽手柄上即可:

修改后的SortableItem组件

const SortableItem: FunctionComponent<{ id: string }> = (props) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    setActivatorNodeRef,
    transform,
    transition,
  } = useSortable({ id: props.id });

  const context: Context = {
    attributes: attributes,
    listeners: listeners,
    setActivatorNodeRef: setActivatorNodeRef
  }

  return (
    <SortableItemContext.Provider value={context}>
      {/* 移除这里的 {...attributes} {...listeners},只保留setNodeRef */}
      <div ref={setNodeRef}>
        {props.children}
      </div>
    </SortableItemContext.Provider>
  );
}

DragHandle组件保持不变

你的DragHandle组件代码是正确的,它已经正确接收了attributes、listeners并绑定了setActivatorNodeRef,无需修改:

export const DragHandle: FunctionComponent = () => {
  const { attributes, listeners, setActivatorNodeRef } = useContext(SortableItemContext);
  return <button type="button"
                 className="DragHandle"
                 {...attributes} {...listeners}
                 ref={setActivatorNodeRef}>
    <svg viewBox="0 0 20 20" width="12">
      <path d="cleaned..."></path>
    </svg>
  </button>
}

其余组件(SortableList及使用示例)无需修改

你的SortableList包装组件和使用示例的代码逻辑正确,不需要调整。

验证效果

修改完成后,只有点击拖拽手柄按钮时才会触发拖拽,列表项的其他区域不会响应拖拽事件,符合预期需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:40:31