使用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);
    }, // 拖拽结束时的回调函数
  });
},
posted @ 2024-06-18 11:20  Cxymds  阅读(96)  评论(1编辑  收藏  举报