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

@dnd-kit/sortable:拖拽含链接的排序项后如何阻止链接跳转

解决@dnd-kit/sortable中拖拽链接后触发跳转的问题

核心思路

拖拽释放时浏览器会把该动作识别为链接点击,进而触发跳转。我们需要区分「正常点击链接」和「拖拽后释放」两种操作,只阻止后者的默认跳转行为。

方案一:通过拖拽状态控制链接点击行为

利用useSortable返回的isDragging状态,在链接的点击事件中判断是否处于拖拽状态,若是则阻止默认跳转:

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

const SortableItem = ({ id, linkUrl }) => {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });

  const itemStyle = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.6 : 1,
  };

  const handleLinkClick = (e) => {
    // 拖拽状态下阻止链接跳转
    if (isDragging) {
      e.preventDefault();
    }
  };

  return (
    <div ref={setNodeRef} style={itemStyle} {...attributes}>
      <a href={linkUrl} onClick={handleLinkClick} {...listeners}>
        可拖拽链接项
      </a>
    </div>
  );
};

方案二:记录拖拽操作状态(更精准)

如果isDragging在释放瞬间快速切换为false,可以通过自定义状态记录拖拽行为,延迟重置确保点击事件能检测到:

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

const SortableItem = ({ id, linkUrl }) => {
  const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
  const [justDragged, setJustDragged] = useState(false);

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

  // 合并拖拽监听,记录拖拽开始/结束状态
  const mergedListeners = {
    ...listeners,
    onDragStart: (e) => {
      listeners.onDragStart(e);
      setJustDragged(true);
    },
    onDragEnd: (e) => {
      listeners.onDragEnd(e);
      // 延迟100ms重置,确保点击事件触发时能捕获到状态
      setTimeout(() => setJustDragged(false), 100);
    },
  };

  const handleLinkClick = (e) => {
    if (justDragged) {
      e.preventDefault();
      setJustDragged(false); // 立即重置,不影响后续正常点击
    }
  };

  return (
    <div ref={setNodeRef} style={itemStyle} {...attributes}>
      <a href={linkUrl} onClick={handleLinkClick} {...mergedListeners}>
        可拖拽链接项
      </a>
    </div>
  );
};

方案三:将拖拽触发区域与链接分离

如果业务允许,可以把拖拽手柄放到链接外面,让用户只能通过手柄拖拽,链接仅响应正常点击:

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

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

  const itemStyle = {
    transform: CSS.Transform.toString(transform),
    transition,
    display: 'flex',
    gap: '8px',
    alignItems: 'center',
  };

  return (
    <div ref={setNodeRef} style={itemStyle} {...attributes}>
      {/* 拖拽手柄 */}
      <button type="button" {...listeners}>
        ☰
      </button>
      {/* 链接仅响应正常点击 */}
      <a href={linkUrl}>普通链接项</a>
    </div>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:40:26