可以建一个mixins文件,可以直接引入组件
需要下载 sortablejs
import Sortable from 'sortablejs'
// 表格拖拽计算逻辑
export default {
data() {
return {
activeRows: [],
// 展开id
expandedRowKeys: []
}
},
mounted() {
this.rowDrop()
},
methods: {
// 修复后的拖拽方法
rowDrop() {
this.$nextTick(() => {
const el = this.$refs.sortableTable.$el.querySelector(
'.el-table__body-wrapper tbody'
)
if (!el) return
const _this = this
Sortable.create(el, {
animation: 300,
// 拖拽目标
handle: '.draggableIcon',
// 拖拽类名 可以设置拖拽的背景
ghostClass: 'sortable-ghost',
onStart() {
_this.activeRows = _this.treeToTile(_this.tableData)
},
onMove({ dragged, related }) {
const oldRow = _this.activeRows[dragged.rowIndex]
const newRow = _this.activeRows[related.rowIndex]
// 不允许跨级拖拽 此处写自己的逻辑(不是树形此处删除即可)
if (oldRow.level !== newRow.level || oldRow.parentId !== newRow.parentId) {
return false
}
return true
},
onEnd({ oldIndex, newIndex }) {
document.body.style.backgroundColor = ''
if (oldIndex === newIndex) return
const movedItem = _this.activeRows[oldIndex]
const targetItem = _this.activeRows[newIndex]
// 确保是同级移动(不是树形此处删除即可)
if (movedItem.level !== targetItem.level) return
// 深拷贝数据
const newData = JSON.parse(JSON.stringify(_this.tableData))
// 从树中移除被拖拽的节点
_this.removeNode(newData, movedItem.id)
// 将节点插入到新位置
_this.insertNode(
newData,
movedItem,
targetItem,
newIndex > oldIndex ? 'after' : 'before'
)
// 更新表格数据
_this.tableData = newData
if (typeof _this.onEndHand === 'function') {
_this.onEndHand(targetItem)
}
_this.$nextTick(() => {
_this.rowDrop()
})
}
})
})
},
// 从树中移除节点
removeNode(tree, id) {
for (let i = 0; i < tree.length; i++) {
if (tree[i].id === id) {
tree.splice(i, 1)
return true
}
if (tree[i].children && tree[i].children.length > 0) {
if (this.removeNode(tree[i].children, id)) {
return true
}
}
}
return false
},
// 将节点插入到树中指定位置
insertNode(tree, node, targetNode, position = 'after') {
for (let i = 0; i < tree.length; i++) {
if (tree[i].id === targetNode.id) {
if (position === 'before') {
tree.splice(i, 0, node)
} else {
tree.splice(i + 1, 0, node)
}
return true
}
if (tree[i].children && tree[i].children.length > 0) {
if (this.insertNode(tree[i].children, node, targetNode, position)) {
return true
}
}
}
return false
},
// 原有方法保持不变
treeToTile(treeData, childKey = 'children') {
const arr = []
const expanded = (data) => {
if (data && data.length > 0) {
data
.filter((d) => d)
.forEach((e) => {
arr.push(e)
expanded(e[childKey] || [])
})
}
}
expanded(treeData)
return arr
},
// 折叠展开id处理
handleExpandChange(row, expanded) {
if (expanded) {
// 展开行
if (!this.expandedRowKeys.includes(row.id)) {
this.expandedRowKeys.push(row.id)
}
} else {
// 折叠行
this.expandedRowKeys = this.expandedRowKeys.filter(
(key) => key !== row.id
)
}
},
// row-key
getRowKey(item) {
return item.id
},
},
}