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

如何实现Jquery UI Sortable表格行仅在所属区块内拖拽排序?

实现jQuery UI Sortable行仅在所属区块内排序的方案

嘿,这个需求我之前做项目的时候刚好遇到过,给你分享几个实用的解决方案,都能实现「行只能在所属区块内排序」的效果:


方案1:利用receive事件阻止跨区块放置(最直接)

核心思路是:给每个可拖拽行标记所属区块ID,当拖拽完成触发receive事件时,检查拖拽行的区块ID和目标位置的区块ID是否一致,不一致就取消拖拽操作。

步骤1:给表格元素添加标识

先给你的表格结构加一些标记,比如用data-block区分区块:

<table id="sortable-table">
  <tbody>
    <!-- 区块1表头(不可拖拽) -->
    <tr class="block-header" data-block="block1">
      <td>区块1</td>
    </tr>
    <!-- 区块1的可拖拽行 -->
    <tr data-block="block1">
      <td>区块1-行1</td>
    </tr>
    <tr data-block="block1">
      <td>区块1-行2</td>
    </tr>

    <!-- 区块2表头(不可拖拽) -->
    <tr class="block-header" data-block="block2">
      <td>区块2</td>
    </tr>
    <!-- 区块2的可拖拽行 -->
    <tr data-block="block2">
      <td>区块2-行1</td>
    </tr>
    <tr data-block="block2">
      <td>区块2-行2</td>
    </tr>
  </tbody>
</table>

步骤2:编写Sortable逻辑

$(function() {
  $("#sortable-table tbody").sortable({
    // 排除区块表头行,不让它们被拖拽
    items: "tr:not(.block-header)",
    // 拖拽完成时触发的事件
    receive: function(event, ui) {
      // 获取被拖拽行的所属区块ID
      const draggedBlock = ui.item.data("block");
      // 找到目标位置对应的区块ID(找拖拽行上方最近的区块表头)
      const targetBlock = ui.item.prevAll(".block-header").last().data("block");

      // 区块不一致则取消拖拽,放回原位置
      if (draggedBlock !== targetBlock) {
        $(this).sortable("cancel");
        // 可选:给用户提示
        alert("只能在当前所属区块内排序哦!");
      }
    },
    // 可选:用克隆元素拖拽,提升视觉体验
    helper: "clone"
  }).disableSelection();
});

方案2:实时检测拖拽位置,提前阻止(更友好)

如果想给用户实时的视觉反馈(比如拖拽到其他区块时高亮禁止状态),可以用over和out事件配合:

JS代码

$(function() {
  $("#sortable-table tbody").sortable({
    items: "tr:not(.block-header)",
    // 拖拽元素进入某行上方时触发
    over: function(event, ui) {
      const draggedBlock = ui.item.data("block");
      // 获取当前鼠标下方行的所属区块
      const targetRow = $(event.target).closest("tr");
      const targetBlock = targetRow.data("block") || targetRow.prevAll(".block-header").last().data("block");

      if (draggedBlock !== targetBlock) {
        // 添加禁止放置的样式
        ui.helper.addClass("cannot-drop");
        // 阻止放置操作
        $(this).sortable("option", "cancel", ".cannot-drop");
      } else {
        ui.helper.removeClass("cannot-drop");
        $(this).sortable("option", "cancel", "");
      }
    },
    // 拖拽元素离开时清除状态
    out: function(event, ui) {
      ui.helper.removeClass("cannot-drop");
      $(this).sortable("option", "cancel", "");
    },
    // 最后再做一次校验,防止遗漏
    receive: function(event, ui) {
      const draggedBlock = ui.item.data("block");
      const targetBlock = ui.item.prevAll(".block-header").last().data("block");
      if (draggedBlock !== targetBlock) {
        $(this).sortable("cancel");
      }
    }
  }).disableSelection();
});

配套CSS(给禁止状态加样式)

.cannot-drop {
  background-color: #ffcccc !important;
  border: 1px solid #ff6666;
}

方案3:拆分区块为独立tbody(最简洁)

如果你的表格结构允许,可以把每个区块拆成独立的<tbody>,这样结合connectWith和receive事件,逻辑会更清晰:

表格结构

<table id="sortable-table">
  <!-- 区块1 -->
  <tbody class="block-container" data-block="block1">
    <tr class="block-header"><td>区块1</td></tr>
    <tr data-block="block1"><td>区块1-行1</td></tr>
    <tr data-block="block1"><td>区块1-行2</td></tr>
  </tbody>
  <!-- 区块2 -->
  <tbody class="block-container" data-block="block2">
    <tr class="block-header"><td>区块2</td></tr>
    <tr data-block="block2"><td>区块2-行1</td></tr>
    <tr data-block="block2"><td>区块2-行2</td></tr>
  </tbody>
</table>

JS代码

$(function() {
  $(".block-container").sortable({
    items: "tr:not(.block-header)",
    // 允许区块间的连接,但后续会限制
    connectWith: ".block-container"
  }).each(function() {
    const currentBlock = $(this);
    // 给每个区块的sortable添加receive事件校验
    currentBlock.sortable("option", "receive", function(event, ui) {
      if (ui.item.data("block") !== currentBlock.data("block")) {
        currentBlock.sortable("cancel");
      }
    });
  }).disableSelection();
});

方案选择建议

  • 如果表格结构可以拆分tbody,优先选方案3,逻辑最简洁,维护成本低;
  • 如果是单tbody用分隔行区分区块,方案1足够满足需求,代码量少;
  • 想要更友好的用户体验,就选方案2,实时反馈更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:42:02