1、最近遇到个需求,需使用vue3+ant design vue +Sortable实现多级表格的表头允许用户拖拽移动。即当用户拖拽一级表头时,其对应的子级表头及数据应同步移动,并且只允许一级非固定表头允许拖拽。
2、代码
<a-table:data-source="rowData2.list":columns="listColumns":pagination="false"bordered:scroll="{ x: 6000, y: 400 }":customRow="onRowClick"ref="tableRef":key="tableKeys"
>
</a-table>import Sortable from 'sortablejs'/** 安全递归重新排序列 */
const reorderColumns = (columns, oldIndex, newIndex) => {if (!Array.isArray(columns)) return columnsconst newColumns = [...columns]// 检查索引是否有效if (oldIndex < 0 ||oldIndex >= newColumns.length ||newIndex < 0 ||newIndex >= newColumns.length) {return columns}const [movedColumn] = newColumns.splice(oldIndex, 1)newColumns.splice(newIndex, 0, movedColumn)return newColumns
}const tableKeys = ref(0)// 添加 watch
watch(tableKeys, () => {nextTick(() => {columnDrop() //重新挂载Sortable})
})/** 列拖拽 */
const columnDrop = () => {const wrapperTr = document.querySelector('.ant-table-thead > tr')// 先销毁旧的 Sortable 实例(如果有)if (wrapperTr && wrapperTr.sortableInstance) {wrapperTr.sortableInstance.destroy()}if (!wrapperTr) {return}// 排除固定列的拖拽const sortable = Sortable.create(wrapperTr, {animation: 180, // ms, number 单位:ms,定义排序动画的时间delay: 0, // number 定义鼠标选中列表单元可以开始拖动的延迟时间;filter: '.ant-table-column-has-sorters', // 不需要进行拖动的元素draggable: '.ant-table-cell:not(.ant-table-cell-fix-left):not(.ant-table-cell-fix-right)', //允许拖拽的项目类名onEnd: (evt) => {// 结束拖拽listColumns.value = reorderColumns(listColumns.value, evt.oldIndex, evt.newIndex)tableKeys.value++ //更新key,解决渲染缓存问题}})
}onMounted(() => {columnDrop()
})
3、遇到的问题:
1、子级表头变化了,一级表头本身页面未变化:解决方法通过key来强制刷新页面。
2、拖拽一次之后就不能继续拖拽了:解决方法通过监听动态销毁Sortable 实例,同时避免了内存泄漏。
3、Sortable 未正确挂载,拖拽不动:解决方法正确设置挂载范围