vxe-table v4 结合 Sortable 实现拖拽排序
大约 2 分钟
需求简介
- 表格带多选框并可全选
- 表格支持手动拖拽排序
- 可选项:实时获取最新的顺序
代码风格依照 jsrun.net 编写,如需融入项目请自行调整。
最终效果
实现过程
复现官方示例拖拽效果并添加多选框
如果不需要实时获取最新的顺序,可忽略后续过程直接使用下面的代码即可
<vxe-table
ref="tableRef"
border
:scroll-y="{enabled: false}"
:row-config="{
useKey: true,
isHover: true,
}"
:checkbox-config="{
strict: true,
range: true,
trigger: 'row',
highlight: true,
}"
@checkbox-change="handleSelectionChange"
@checkbox-all="handleSelectionChange"
@checkbox-range-end="handleSelectionChange"
:data="tableData"
>
<vxe-column width="60">
<template #header>
<vxe-tooltip content="按住后可以上下拖动排序!" enterable>
<i class="vxe-icon-question-circle-fill"></i>
</vxe-tooltip>
</template>
<template #default>
<span class="drag-btn">
<i class="vxe-icon-edit"></i>
</span>
</template>
</vxe-column>
<vxe-column type="checkbox" width="55" fixed="left"></vxe-column>
<vxe-column field="id" title="主键"></vxe-column>
<vxe-column field="name" title="Name"></vxe-column>
</vxe-table>
<button type="button" @click="submit">获取已选项</button>
var Main = {
data () {
return {
tableData: [],
ids: [],
}
},
mounted () {
this.init();
},
methods: {
submit() {
// 由于 vxe-table 默认勾选项排序是按用户的点击顺序排列,需要手动处理一下
const ids = this.getIds();
console.log(ids);
},
handleSelectionChange({ records }) {
// TODO: 如果无需实时获取,可删除此方法
this.ids = this.getIds(records);
},
getIds(checkboxRecords = []) {
if (checkboxRecords.length === 0) { return []; }
const tableIds = this.tableData.map(item => item.id);
let list = checkboxRecords;
const newIds = tableIds.filter(id => {
return list.find(fid => fid == id);
});
return newIds;
},
init() {
var list = []
for(var index = 0; index < 3; index++){
list.push({
id: index + 1,
name: 'test' + index,
})
}
this.tableData = list
this.$nextTick(() => {
this.rowDrop();
})
this.ids = [];
},
rowDrop() {
if (this.sortable1) {
this.sortable1.destroy();
this.sortable1 = false;
}
const $table = this.$refs.tableRef
this.sortable1 = Sortable.create($table.$el.querySelector('.body--wrapper>.vxe-table--body tbody'), {
handle: '.drag-btn',
animation: 300,
ghostClass: "ghost",
onEnd: ({newIndex, oldIndex}) => {
const currRow = this.tableData.splice(oldIndex, 1)[0]
this.tableData.splice(newIndex, 0, currRow)
}
})
}
},
destroyed() { // 销毁
if (this.sortable1) {
this.sortable1.destroy();
this.sortable1 = false;
}
}
};
Vue.createApp(Main).use(VXETable).mount('#app')
错误方法
当时的想法是,每当手动拖拽排序后,从已勾选的列表中找到对换位置的项更换一下位置就行。 但是出现下面这种情况时,勾选项与表格显示项就异常混乱
用户不按表格顺序勾选,比如先勾选第五行再勾选第一行。
可以在上面在线预览内容放开测试
rowDrop() {
if (this.sortable1) {
this.sortable1.destroy();
this.sortable1 = false;
}
const $table = this.$refs.tableRef
this.sortable1 = Sortable.create($table.$el.querySelector('.body--wrapper>.vxe-table--body tbody'), {
handle: '.drag-btn',
animation: 300,
ghostClass: "ghost",
onEnd: ({newIndex, oldIndex}) => {
// TODO: 实时获取排序的错误方法
const newId = this.tableData[newIndex].id;
const oldId = this.tableData[oldIndex].id;
const findNewId = this.ids.findIndex(item => item == newId);
const findOldId = this.ids.findIndex(item => item == oldId);
if (findNewId != -1 && findOldId != -1) {
const currRowId = this.ids.splice(findOldId, 1)[0];
this.ids.splice(findNewId, 0, currRowId);
}
const currRow = this.tableData.splice(oldIndex, 1)[0]
this.tableData.splice(newIndex, 0, currRow)
}
})
}
正确方法
rowDrop() {
if (this.sortable1) {
this.sortable1.destroy();
this.sortable1 = false;
}
const $table = this.$refs.tableRef
this.sortable1 = Sortable.create($table.$el.querySelector('.body--wrapper>.vxe-table--body tbody'), {
handle: '.drag-btn',
animation: 300,
ghostClass: "ghost",
onEnd: ({newIndex, oldIndex}) => {
const currRow = this.tableData.splice(oldIndex, 1)[0]
this.tableData.splice(newIndex, 0, currRow);
// TODO: 实时获取排序的正确方法
const tableIds = this.tableData.map(item => item.id);
const newIds = tableIds.filter(id => {
return this.ids.find(fid => fid == id);
});
this.ids = newIds;
}
})
}