因为ant-design表格组件没有封装拖拽排序的方法,需要通过customRow这个属性进行自定义排序。
因为项目的原因所以使用的是typescript
THML代码
<a-table :customRow="customRow" :columns="columns" :data-source="dataSource">
........
</a-table>
TypeScript代码
// 位置记录
const position = {
start: undefined as number | undefined,
end: undefined as number | undefined,
sourceEl: undefined as undefined | HTMLTableRowElement,
}
// 排序
const reorder = ({ 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`
})
}
变量dataSource是绑定的表格的数据源,替换成自己的就可以了。
动画效果原理:通过获取开始位置和结束位置计算位移距离,添加动画时间然后,在下一次事件循环的时候将偏移设置为0既可以实现排序的动画效果。