使用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);
}, // 拖拽结束时的回调函数
});
},