使用sortablejs 实现el-table拖拽排序

本质上还是js的拖拽API,也可以使用原生的drag系列函数(dragstart、drag、dragend、dragover、drop、dragleave)实现。这里介绍使用sortablejs 插件快速实现拖拽排序这个功能。

1. 安装sortablejs

官网(https://sortablejs.com)提供了各种环境的安装方式,这里使用前端最常见的npm包安装

npm install sortablejs --save

2. 使用

在项目中引入插件

import Sortable from ‘sortablejs’

在mounted生命周期函数中创建对象实例

一定要在nextTick里面去做调用,否则有可能不生效

mounted(){
  this.$nextTick(() => {
		this.initSortTable();
	});	
}

在methods中创建initSortTable 函数

initSortTable() {
  // 获取 el-table
  const tableTag = this.$refs['tableView'].$el;
  // 获取 tbody 节点
  const elTbody = tableTag.querySelectorAll('.el-table__body-wrapper > table > tbody')[0];
  new Sortable(elTbody, {
    animation: 150, // 拖拽时的动画速度,单位为毫秒
    handle: '.el-table__row', // 拖拽的手柄元素,这里使用表格的行作为手柄
    onEnd: (evt) => {
      this.dragSort(evt);// 拖拽结束时的回调函数
    }, 
  });
},

到此基本已经实现可以拖拽表格的行进行移动排序。

当然还是需要结合后端实现排序的记录。可以在这里的dragSort中调用后端接口进行结果保存。

dragSort(event) {
  //前端排序数据处理
  const movedItem = this.tableData.splice(event.oldIndex, 1)[0];
  this.tableData.splice(event.newIndex, 0, movedItem);
  this.$forceUpdate(); // 强制更新组件
  //调用后端接口
},

3. 优化

3. 1 可拖拽范围

目前为止,可以实现整个table行拖拽的时候进行排序,但是也会有写问题,当前行拖拽的范围有点大,可能会有很多误触的情况,

此时只需要修改Sortable参数的handle 即可。可以在表格行中添加一个按钮,将这个按钮设置为handle。这样就可以实现将拖拽响应绑定在一个按钮的范围。

new Sortable(elTbody, {
  animation: 150, // 拖拽时的动画速度,单位为毫秒
  handle: '.drag-item', // 拖拽的手柄元素,这里使用表格的行作为手柄
  onEnd: (evt) => {
    this.dragSort(evt); // 拖拽结束时的回调函数
  }, 
});

3.2 固定表格列造成的拖拽数据串行

我们经常会将表格的最后一行进行固定,例如:

<el-table-column label="操作" width="240" fixed="right">
  <template slot-scope="scope">
    <el-button size="mini" plain @click="$refs.editRef.openDialog(scope.row.uuid, true)">修改</el-button>
    <el-button size="mini" plain @click="$refs.editRef.openDialog(scope.row.uuid, false)">查看</el-button>
    <el-button type="warning" size="mini" plain @click="deleteItem(scope.row)">删除</el-button>
    <el-button size="mini" icon="el-icon-d-caret" plain class="drag-item">排序</el-button>
  </template>
</el-table-column>

此时拖着排序按钮会造成scope中的数据与所对应的行错乱,这是因为在el-table组件中,fixed中的内容并不会与表格其他内容创建在同一行中,而是创建了多个表格。如下图:

所以我们在获取table节点的时候就不能使用前面的数据table,而是使用后面的操作单元表格el-table__fixed-body-wrapper

initSortTable() {
  // 获取 el-table
  const tableTag = this.$refs['tableView'].$el;
  // 获取 tbody 节点
  const elTbody = tableTag.querySelectorAll('.el-table__fixed-body-wrapper > table > tbody')[0];
  new Sortable(elTbody, {
    animation: 150, // 拖拽时的动画速度,单位为毫秒
    handle: '.drag-item', // 拖拽的手柄元素,这里使用表格的行作为手柄
    onEnd: (evt) => {
      this.dragSort(evt);
    }, // 拖拽结束时的回调函数
  });
},

以下为园子小伙伴指正意见

使用sortablejs 实现el-table拖拽排序
dragSort(event) {
//前端排序数据处理
const movedItem = this.tableData.splice(event.oldIndex, 1)[0];
this.tableData.splice(event.newIndex, 0, movedItem);
this.$forceUpdate(); // 强制更新组件
//调用后端接口
},
方法的时候会出现数据错乱 可以使用下面这个方法来避免
const oldRow = this.tableData[event.oldIndex]
this.tableData[event.oldIndex] = this.tableData[event.newIndex]
this.tableData[event.newIndex] = oldRow
这种调换顺序的方式不改变原来绑定的table数组数据时没有问题
如果要改变el-table中的sort等顺序可以在表格上面添加
row-key="id"
给每个行指定一个key
然后更新那里使用$set方法
//这里使用$set方式是告诉el-table 绑定的数据值发生变化,需要重新渲染
this.$set(this.tableData, event.oldIndex, this.tableData[event.newIndex])
this.$set(this.tableData, event.newIndex, oldRow)
this.$forceUpdate() // 强制更新组件
posted @   Cxymds  阅读(1166)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示