问题描述:在vue3+ant design vue+ts的项目中遇到了需要实现表格拖拽行进行排序的功能,翻遍了第三方插件使用未果,例如sortablejs,失败案例就不在此处过多赘述了,直接展示成功的写法,希望可以帮到有类似功能的朋友。
<Table
:dataSource="dataSource"
:columns="columns"
showIndexColumn
:customRow="customRow"
size="small"
>
<template #action="{ record }">
<Button type="link">删除</Button>
<Button type="link" v-if="record.type == '0'">隐藏</Button>
<Button type="link" v-else>取消隐藏</Button>
</template>
</Table>
引入
import { Table, Button } from 'ant-design-vue';
主要代码
// 位置记录
const position = {
start: undefined as number | undefined,
end: undefined as number | undefined,
sourceEl: undefined as undefined | HTMLTableRowElement,
};
// 排序
const reorder = ({ start, end }) => {
console.log('676868', start, end);
if (start !== undefined && end !== undefined) {
if (start > end) {
// 当开始大于结束
let temp = dataSource.value[start];
dataSource.value.splice(start, 1);
dataSource.value.splice(end, 0, temp);
} else if (start < end) {
// 结束大于开始
let temp = dataSource.value[start];
dataSource.value.splice(start, 1);
dataSource.value.splice(end + 1, 0, temp);
}
let arr: string[] = dataSource.value?.map((item: any) => item.id);
emit('onDeviceList', arr);
}
};
function customRow(_record, index) {
return {
style: {
cursor: 'move',
},
// 鼠标移入
onMouseenter: (event) => {
// 兼容IE
let ev = event || window.event;
ev.target.draggable = true;
},
// 开始拖拽
onDragstart: (event) => {
// 兼容IE
let ev = event || window.event;
// 阻止冒泡
ev.stopPropagation();
// 得到源目标数据;
position.start = index;
const tr = ev.target as HTMLTableRowElement;
position.sourceEl = tr;
},
// 拖动元素经过的元素
onDragover: (event) => {
let ev = event || window.event;
// 阻止默认行为
ev.preventDefault();
},
// 松开
onDrop: (event) => {
let ev = event || window.event;
// 阻止默认行为
ev.preventDefault();
position.end = index;
reorder(position);
animation(position);
},
};
}
// 实现动画效果
function animation({ start, end, sourceEl }) {
// 48 是每行的高度,也可以自动获取,根据情况而定
let count = 48 * (start! - end!);
sourceEl.style.translate = `0px ${count}px`;
setTimeout(() => {
sourceEl!.style.transition = 'all 0.5s';
sourceEl!.style.translate = `0px 0px`;
});
}
此案例代码亲测有用