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 未正確掛載,拖拽不動:解決方法正確設置掛載范圍