一. 介绍
sortablejs是一款功能强大的JavaScript 拖拽库,我的使用一般是在table表格中使用,但它的功能远不止于此,这里只记录下在使用sortablejs进行table表格拖拽中遇到的问题。Vue3 element plus配合使用
二. 使用
1. 安装
npm i sortablejs -S
2. 引用
import Sortable from 'sortablejs';
3. 初始化使用
创建实例时传入两个参数,第一个为包裹的父元素,第二个为配置对象。 详情配置见中文官网sortablejs中文官网
<template>
<div v-if='dialogFormVisible'>
<el-table
:data="nodeTableData"
:row-key="nodeId"
ref="myTable"
:row-class-name="filter_row"
>
<el-table-column width="80" label="排序"></el-table-column>
...
...
</el-table>
</div>
</template>
<script>
import { defineComponent, ref, watch, nextTick } from 'vue';
import Sortable from 'sortablejs';
export default defineComponent({
setup() {
let myTable = ref(null);
let dialogFormVisible = ref(false)
drag() {
const el1 = myTable.value.$refs.tableBody.children[1];
new Sortable(el1, {
disabled: false, // 是否开启拖拽
ghostClass: 'sortable-ghost', //拖拽样式
animation: 150, // 拖拽延时,效果更好看
filter: '.filter_row',
group: {
// 是否开启跨表拖拽
pull: false,
put: false,
},
onEnd: function(e) {
// 这里主要进行数据的处理,拖拽实际并不会改变绑定数据的顺序,这里需要自己做数据的顺序更改
if (e.oldIndex == e.newIndex) return;
const currRow = nodeTableData.value.splice(e.oldIndex, 1)[0];
nodeTableData.value.splice(e.newIndex, 0, currRow);
if (e.newIndex === 0 || e.newIndex === nodeTableData.value.length - 1) {
//复原数据
let item = nodeTableData.value.splice(e.newIndex, 1)[0];
nodeTableData.value.splice(e.oldIndex, 0, item);
// 复原拖拽之前的 dom
const tagName = e.item.tagName;
const items = e.from.getElementsByTagName(tagName);
if (e.oldIndex > e.newIndex) {
e.from.insertBefore(e.item, items[e.oldIndex + 1]);
} else {
e.from.insertBefore(e.item, items[e.oldIndex]);
}
ElMessage.error('不可修改');
return;
}
// 如数据有排序数据的需要去同步更改
nodeTableData.value.forEach((item, index) => {
item.nodeSort = index + 1;
});
if (!isAdd.value) {
let needEditNode = [];
let params = { list: [] };
if (e.newIndex > e.oldIndex) {
//下移
needEditNode = nodeTableData.value.filter((item, index) => index >= e.oldIndex);
params.list = needEditNode.map((item) => {
return { nodeId: item.nodeId, nodeSort: item.nodeSort };
});
xxx(params);//发送的后台请求
} else {
//上移
needEditNode = nodeTableData.value.filter((item, index) => index >= e.newIndex);
params.list = needEditNode.map((item) => {
return { nodeId: item.nodeId, nodeSort: item.nodeSort };
});
xxx(params);//发送的后台请求
}
}
},
})
}
watch(
() => dialogFormVisible.value,
(newV) => {
if (newV) {
nextTick(() => drag());
}
},
{ immediate: true },
);
return {
myTable,
dialogFormVisible
}
}
})
</script>
三. 一些问题
1. 关于找不到元素的问题
这里的table表格是在一个弹框里的,由dialogFormVisible状态去显示隐藏,必须通过watch去监听当元素创建后在去做实例的初始化。如果只是页面中的table拖拽就比较简单不需要这样了。可通过打印去找到实际包裹的父元素。
2. filter配置问题
如果有需求说明那些行不可拖拽的,如(首行和尾行不可拖拽)可以使用element UI中table的row-class-name属性去自定义添加某行的类名。
3. 当filter后,当前元素是不可拖拽但其他元素还是可以拖拽到它的位置,影响需求。
可通过判断新拖拽到的位置是否是filter的行,在复原拖拽前的dom
if (e.newIndex === 0 || e.newIndex === nodeTableData.value.length - 1) {
//复原数据
let item = nodeTableData.value.splice(e.newIndex, 1)[0];
nodeTableData.value.splice(e.oldIndex, 0, item);
// 复原拖拽之前的 dom
const tagName = e.item.tagName;
const items = e.from.getElementsByTagName(tagName);
if (e.oldIndex > e.newIndex) {
e.from.insertBefore(e.item, items[e.oldIndex + 1]);
} else {
e.from.insertBefore(e.item, items[e.oldIndex]);
}
ElMessage.error('不可修改');
return;
}