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

实现表格行上下拖拽移动功能需求求助

表格行拖拽移动实现方案

需求:给五列表格添加行上下拖拽调整位置的功能,要求用户悬停在某一行时,第一列的拖拽按钮显示,点击该按钮可拖动该行进行上下位置调整。

以下是基于React的原生实现方案,无需依赖第三方拖拽库:

实现步骤

  1. 状态管理:维护表格数据数组,以及拖拽过程中的临时状态(当前拖拽行索引、拖拽中状态)
  2. 鼠标事件处理:实现拖拽开始、拖拽中、拖拽结束的逻辑,通过数组元素交换完成行位置调整
  3. 样式优化:添加拖拽过程中的视觉反馈,提升用户操作感知

完整代码实现

import { useState } from 'react';
import AppsIcon from '@mui/icons-material/Apps';

export default function App() {
  // 示例数据,替换为你的实际业务数据
  const [nodes, setNodes] = useState([
    { name: '行1', length: 10, hotkey: 'Ctrl+A', isActivness: true },
    { name: '行2', length: 20, hotkey: 'Ctrl+B', isActivness: false },
    { name: '行3', length: 15, hotkey: 'Ctrl+C', isActivness: true },
    { name: '行4', length: 5, hotkey: 'Ctrl+D', isActivness: false },
  ]);
  const [draggingIndex, setDraggingIndex] = useState(null);
  const [hoverIndex, setHoverIndex] = useState(null);

  // 触发拖拽,记录当前拖拽行索引
  const handleDragStart = (index) => {
    setDraggingIndex(index);
  };

  // 拖拽过程中,实时交换行位置
  const handleDragOver = (e, index) => {
    e.preventDefault();
    if (draggingIndex === index) return;

    const newNodes = [...nodes];
    // 交换拖拽行与当前悬停行的位置
    const draggedItem = newNodes[draggingIndex];
    newNodes.splice(draggingIndex, 1);
    newNodes.splice(index, 0, draggedItem);

    setNodes(newNodes);
    setDraggingIndex(index);
    setHoverIndex(index);
  };

  // 结束拖拽,清空临时状态
  const handleDragEnd = () => {
    setDraggingIndex(null);
    setHoverIndex(null);
  };

  return (
    <table className="zui">
      <tbody style={{ fontSize: "40px" }}>
        {nodes.map((val, key) => (
          <tr
            key={key}
            className={hoverIndex === key ? 'drag-hover' : ''}
          >
            <td>
              <AppsIcon
                className="sss"
                draggable
                onDragStart={() => handleDragStart(key)}
                onDragOver={(e) => handleDragOver(e, key)}
                onDragEnd={handleDragEnd}
                style={{ cursor: draggingIndex === key ? 'grabbing' : 'grab' }}
              />
            </td>
            <td style={{ paddingLeft: "20px" }}>
              {val.name}
            </td>
            <td>{val.length}</td>
            <td>{val.hotkey}</td>
            <td>{val.isActivness ? '激活' : '未激活'}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

更新后的样式(styles.css)

.sss {
  visibility: hidden;
  transition: visibility 0.2s ease;
}

tr:hover .sss {
  visibility: visible;
}

tr:hover {
  background-color: #f0f0f0;
}

/* 拖拽悬停行的高亮样式 */
tr.drag-hover {
  background-color: #e0e0e0;
}

td:first-child {
  border-top-left-radius: 5px;
  border-bottom-left-radius: 5px;
}

td:last-child {
  border-top-right-radius: 5px;
  border-bottom-right-radius: 5px;
}

核心逻辑说明

  • 仅给第一列的拖拽图标开启draggable属性,避免整行误触发拖拽
  • 在onDragOver事件中实时交换数组元素位置,实现拖拽过程中行位置的即时更新
  • 通过drag-hover类和图标光标变化,提供清晰的拖拽状态反馈

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:23:14