实现的功能:
- 该树形表只有一级子节点
- 该子节点只能在当前父节点中拖拽, 不能跨父节点拖拽
- 同时只能展开一个父节点, 其他父节点闭合
实现的关键点:
- mounted 挂载 初始化sortable
- 拖拽完onEnd方法返回的index是整个列表的排序,要扁平化数组
调用该方法getTable() - 后台多返回一个kid,和id的值一样,用来更新tableData
- 拖拽完成要把el-table中的row-key对应的kid重新生成,父节点和子节点绑定的kid都要重新生成,让el-table局部刷新,不然会出现父节点移除,子节点还是在原有的位置,但是tableData中已经是最新的数据
- 拖拽完成之后调用接口保存当前排序
参数格式:如果拖拽父节点,只传父节点排序 convertMap对象
如果拖拽子节点,传子节点排序 convertMapChild对象
//树形数组扁平化
getTable(data) {
data.forEach(d => {
const obj = {
...d,
cid: [],
}
delete obj.children
this.tempData.push(obj)
if (d.children && d.children.length > 0) {
d.children.forEach(c => {
obj.cid.push(c.id)
})
this.getTable(d.children)
}
})
},
mounted时调用的方法
rowDrop() {
const tb = document.querySelector('tbody')
Sortable.create(tb, {
handle: '.drop',
animation: 180,
delay: 0,
onEnd: ({ newIndex, oldIndex }) => {
this.idIndexMap()
this.newIndex = newIndex
this.oldIndex = oldIndex
this.tempData = []
this.getTable(this.tableData)
const newData = this.tempData.at(newIndex)
const delData = this.tempData.at(oldIndex)
//第一层级移动,删除拖拽节点,包括拖拽节点的子节点,更新convertMap,id对应的索引
if (delData.cid && delData.cid.length > 0 || delData.parentId === 0) {
const delTdIndex = this.convertMap[delData.id]
const newTdIndex = this.convertMap[newData.id]
const [dd] = this.tableData.splice(delTdIndex, 1)
dd.kid = this.getUuid()
dd.children.map(d => {
d.kid = this.getUuid()
return d
})
this.tableData.splice(newTdIndex, 0, dd)
this.idIndexMap()
} else if (newData.parentId === delData.parentId) {
//子层级移动 重新生成convertMapChild,更新id对应的索引
const parentIndex = this.convertMap[newData.parentId]
const parentData = this.tableData[parentIndex]
const children = parentData.children
this.generateIdToIndexChild(children)
children.splice(this.convertMapChild[delData.id], 1)
children.splice(this.convertMapChild[newData.id], 0, delData)
this.generateIdToIndexChild(children)
}
},
//选择的时候记住拖拽节点的索引
onChoose: ({ oldIndex }) => {
this.oldIndex = oldIndex
},
onMove: (customEvent, dragEvent) => {
//移动到新节点会有新节点的索引,和拖拽节点的父id进行
//比较,如果不一致,不让拖拽,返回false
this.tempData = []
this.getTable(this.tableData)
this.newIndex = customEvent.related.rowIndex
const newData = this.tempData.at(this.newIndex)
const delData = this.tempData.at(this.oldIndex)
if (newData.parentId !== delData.parentId) {
return false
}
}
})
},
拖拽一级节点先转化为 id--index的对应关系
idIndexMap() {
this.convertMap = this.tableData.reduce((acc, cur, index) => {
return {
...acc,
[cur.id] : index
}
}, {})
},
拖拽子节点生成Map id--index的对应关系
generateIdToIndexChild(children) {
console.log(children);
this.convertMapChild = children.reduce((acc, cur, index) => {
return {
...acc,
[cur.id] : index
}
}, {})
},
标签:el,sortable,children,delData,id,节点,js,拖拽,const
From: https://www.cnblogs.com/tangshidedabenniao/p/17985503