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

Vue.draggable实现两个可拖拽表格间的交换功能问题咨询

实现两个可拖拽表格的条目交换功能

核心配置要点

  • 两个<draggable>组件需设置相同的group名称,开启跨列表拖拽权限
  • 表格1固定7条数据,限制为交换模式:拖拽表格2条目到表格1时,替换目标位置原有条目,而非新增
  • 跨列表拖拽触发时弹出确认对话框,用户确认后执行交换,否则回滚数据
  • 可通过钩子禁止表格1内部拖拽排序,保留固定条目的结构

完整代码实现

<template>
  <div class="table-container">
    <!-- 表格1:固定7条条目 -->
    <table>
      <thead>
        <tr><th>ID</th><th>姓名</th><th>年龄</th></tr>
      </thead>
      <draggable 
        v-model="table1Items" 
        tag="tbody" 
        :group="{ name: 'table-group' }"
        @end="handleDragEnd"
        :move="handleMove"
        :options="{ animation: 500 }"
      >
        <tr v-for="item in table1Items" :key="item.id">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.age }}</td>
        </tr>
      </draggable>
    </table>

    <!-- 表格2:其他条目 -->
    <table>
      <thead>
        <tr><th>ID</th><th>姓名</th><th>年龄</th></tr>
      </thead>
      <draggable 
        v-model="table2Items" 
        tag="tbody" 
        :group="{ name: 'table-group' }"
        @end="handleDragEnd"
        :options="{ animation: 500 }"
      >
        <tr v-for="item in table2Items" :key="item.id">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.age }}</td>
        </tr>
      </draggable>
    </table>
  </div>
</template>

<script>
import draggable from "vuedraggable";

export default {
  components: { draggable },
  data() {
    return {
      // 表格1:固定7条示例数据
      table1Items: [
        { id: 1, name: "Alice", age: 25 },
        { id: 2, name: "Bob", age: 30 },
        { id: 3, name: "Charlie", age: 28 },
        { id: 4, name: "David", age: 35 },
        { id: 5, name: "Eve", age: 22 },
        { id: 6, name: "Frank", age: 40 },
        { id: 7, name: "Grace", age: 27 }
      ],
      // 表格2:其他示例数据
      table2Items: [
        { id: 8, name: "Henry", age: 32 },
        { id: 9, name: "Iris", age: 24 },
        { id: 10, name: "Jack", age: 38 }
      ],
      // 保存拖拽前的状态,用于取消时回滚
      prevState: {}
    };
  },
  methods: {
    handleMove(evt) {
      // 禁止表格1内部的拖拽排序
      const isSameTable1 = evt.from._vnode.data.model.value === this.table1Items && evt.to._vnode.data.model.value === this.table1Items;
      return !isSameTable1;
    },
    handleDragEnd(evt) {
      const { draggedContext, to, from } = evt;
      // 同列表拖拽直接返回
      if (from === to) return;

      // 判断是否是表格2到表格1的跨列表拖拽
      const isCrossDrag = from._vnode.data.model.value === this.table2Items && to._vnode.data.model.value === this.table1Items;
      if (!isCrossDrag) return;

      // 保存拖拽前的完整状态
      this.prevState = {
        table1: [...this.table1Items],
        table2: [...this.table2Items],
        draggedItem: draggedContext.item,
        targetIndex: evt.toIndex,
        sourceIndex: draggedContext.index
      };

      // 弹出确认对话框
      const confirmSwap = confirm('确定要交换这两个条目吗?');
      if (confirmSwap) {
        // 执行交换逻辑
        const table1TargetItem = this.table1Items[this.prevState.targetIndex];
        // 移除表格2的拖拽项
        this.table2Items.splice(this.prevState.sourceIndex, 1);
        // 替换表格1目标位置的条目
        this.table1Items.splice(this.prevState.targetIndex, 1, this.prevState.draggedItem);
        // 将表格1原条目添加到表格2
        this.table2Items.push(table1TargetItem);
      } else {
        // 用户取消,回滚到拖拽前状态
        this.table1Items = this.prevState.table1;
        this.table2Items = this.prevState.table2;
      }
    }
  }
};
</script>

<style scoped>
.table-container {
  display: flex;
  gap: 20px;
  padding: 20px;
}
table {
  border-collapse: collapse;
  border: 1px solid #ddd;
  min-width: 300px;
}
th, td {
  padding: 8px 12px;
  border: 1px solid #ddd;
  text-align: left;
}
th {
  background-color: #f5f5f5;
}
tr:hover {
  background-color: #f9f9f9;
}
</style>

关键逻辑说明

  1. 跨列表拖拽配置:两个<draggable>的group.name设为相同值,允许组件间的拖拽交互。
  2. 内部拖拽拦截:通过handleMove钩子禁止表格1内部的拖拽排序,确保只能进行跨列表交换。
  3. 拖拽状态判断:在handleDragEnd中通过数据源判断是否为表格2到表格1的跨列表操作,过滤无效交互。
  4. 确认与回滚:拖拽前保存两个表格的原始数据,用户取消时直接恢复;确认后执行交换逻辑,保证表格1始终保持7条数据。
  5. 交换逻辑实现:移除表格2的拖拽项,替换表格1目标位置的条目,再将表格1原条目添加到表格2,完成双向交换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:25:57