在 Vue3 + Element Plus 中实现 el-table 拖拽排序功能

2,571 阅读2分钟
# 在 Vue3 + Element Plus 中实现 el-table 拖拽排序功能

在实际项目中,表格字段经常需要自定义排序,Element Plus 的 `el-table` 虽然功能丰富,但并不内置支持“行拖拽”排序。我们可以借助 [SortableJS](https://github.com/SortableJS/Sortable) 来实现表格拖拽功能。

本文将以 Vue3 + Element Plus + SortableJS 为例,介绍如何实现一个支持拖拽排序的表格组件。

---

## 📦 安装依赖

```bash
npm install sortablejs --save

可选:如果你使用 vuedraggable 也可以实现类似功能。


📐 表格模板设计

使用 el-table 组件,添加一列拖拽手柄:

<el-table
  ref="dragTable"
  :data="tableFields"
  stripe
  height="310px"
  row-key="columnName"
>
  <el-table-column label="序号" width="80" align="center">
    <template #default="{ $index }">
      <div class="allowDrag" style="cursor: move;">
        <el-icon><SortDescending /></el-icon>
        <span style="margin-left: 4px;">{{ $index + 1 }}</span>
      </div>
    </template>
  </el-table-column>

  <!-- 其他字段列... -->
</el-table>

🧠 拖拽逻辑实现

import Sortable from "sortablejs";
import { nextTick, ref } from "vue";

const dragTable = ref(null);
let sortableInstance = null;

function setSort() {
  nextTick(() => {
    const tbody = dragTable.value?.$el.querySelector(".el-table__body-wrapper tbody");
    if (!tbody) {
      console.warn("tbody 不存在,拖拽初始化失败");
      return;
    }

    // 销毁旧实例
    if (sortableInstance) {
      sortableInstance.destroy();
    }

    // 创建新的拖拽实例
    sortableInstance = Sortable.create(tbody, {
      handle: ".allowDrag", // 指定拖拽区域
      animation: 150,
      onEnd: (evt) => {
        const movedItem = tableFields.value.splice(evt.oldIndex, 1)[0];
        tableFields.value.splice(evt.newIndex, 0, movedItem);
        console.log("拖拽结果:", tableFields.value.map(f => f.columnName));
      },
    });
  });
}

📌 注意事项

  • el-table 必须设置 row-key,否则排序后渲染会异常。
  • 每次添加、删除字段后需要重新调用 setSort() 初始化拖拽。
  • 推荐限制拖拽区域(如加 .allowDrag)避免误触。

➕ 添加字段时绑定拖拽

function handleAddField() {
  tableFields.value.push({
    columnName: "new_col",
    order: "asc",
    caseSensitive: false,
    locale: true,
    collatorStrength: 0,
    presorted: false
  });
  setSort(); // 重要!
}

❌ 删除字段时也需刷新拖拽

function handleDelete(row) {
  const index = tableFields.value.findIndex(f => f.columnName === row.columnName);
  if (index !== -1) tableFields.value.splice(index, 1);
  setSort(); // 删除后刷新拖拽
}

✅ 效果展示

  • 支持拖动 el-table 的行进行重新排序。
  • 拖动手柄为 <el-icon><SortDescending /></el-icon> 图标。
  • 拖拽后数据源顺序实时更新。

🧩 总结

结合 SortableJS 与 Vue3 的响应式特性,我们可以轻松为 Element Plus 的表格添加拖拽排序功能:

  • ✅ 操作流畅
  • ✅ 实时更新数据
  • ✅ 可组合其他逻辑(如保存顺序、回显等)

后续可将其封装为通用组件,支持传入字段、控制排序、导出顺序等功能。


📚 参考


---

如需我帮你封装为 `md` 文件或补充封面图、适配组件封装部分,也可以继续提问。