第一步:安装sortablejs
npm install sortablejs --save
第二步:在需要的地方引入
import Sortable from 'sortablejs'
第三步准备需要的表格,推拽处理逻辑完整代码
<template>
<div>
<el-table ref="dragTable" row-key="id" :data="treeTableData" :expand-row-keys="treeTableExpandKeys" border
@expand-change="treeTableExpandChange">
<el-table-column prop="name" label="名字"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="desc" label="描述"></el-table-column>
</el-table>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
data() {
return {
treeTableData: [
{
id: '1',
name: '盖伦',
age: 11,
desc: '寒冰',
children: [
{
id: '2',
name: '光辉',
age: 15,
desc: '加里奥',
children: [
{
id: '6',
name: '女警',
age: 15,
desc: '人马'
}
]
},
{
id: '23',
name: '潘森',
age: 15,
desc: '22',
children: [
{
id: '45',
name: '剑圣',
age: 15,
desc: '阿卡丽'
},
{
id: '42',
name: '锐雯',
age: 15,
desc: '塞恩'
}
]
}
]
},
{
id: '3',
name: '凌不疑',
age: 18,
desc: '三三',
children: [
{
id: '4',
name: '四四',
age: 25,
desc: '五五'
},
{
id: '5',
name: '不知道叫什么了',
age: 26,
desc: '哈哈哈'
}
]
}
],
flatTreeData: [],
treeTableExpandKeys: [],
sortableObj: null
}
},
mounted() {
this.transverseNode(this.treeTableData, 1, (node, level, parentNode) => {
node.level = level
console.log(parentNode,'parentNode');
node.parentId = parentNode ? parentNode.id : -1
console.log(node,'node');
})
this.initSortable()
console.log(this.flatTreeData,77);
this.getFlatNode(this.treeTableData, this.flatTreeData)
},
beforeDestroy() {
if (this.sortableObj) {
this.sortableObj.destroy()
}
},
methods: {
initSortable() {
// 获取容器元素
const el = this.$refs.dragTable.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
if (!el) return
this.sortableObj = new Sortable(el, {
group: 'dragName',
draggable: '.el-table__row',
onEnd: evt => {
const { newIndex, oldIndex } = evt
const dragRow = this.flatTreeData[oldIndex]
const relatedRow = this.flatTreeData[newIndex]
if (dragRow.parentId !== relatedRow.parentId) {
this.$message.warning('只能同层级内排序')
this.reRender(null, 'treeTableData')
} else {
// 都无children
if (!dragRow.children && !relatedRow.children) {
const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
this.flatTreeData.splice(newIndex, 0, oldData)
}
// drag有, relate无
if (dragRow.children && !relatedRow.children) {
const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
this.flatTreeData.splice(newIndex, 0, oldData)
if (newIndex < oldIndex) {
// 有子元素的,子元素需要同样跟上来
const flatChildren = []
this.getFlatNode(oldData.children || [], flatChildren)
if (flatChildren.length > 0) {
for (let i = 1, len = flatChildren.length; i <= len; i++) {
const childData = this.flatTreeData.splice(oldIndex + i, 1)[0]
this.flatTreeData.splice(newIndex + i, 0, childData)
}
}
} else {
// 有子元素的,子元素需要同样跟下来
const flatChildren = []
this.getFlatNode(oldData.children || [], flatChildren)
if (flatChildren.length > 0) {
for (let i = 1, len = flatChildren.length; i <= len; i++) {
const childData = this.flatTreeData.splice(oldIndex, 1)[0]
this.flatTreeData.splice(newIndex, 0, childData)
}
}
}
}
// drag无, relate有
if (!dragRow.children && relatedRow.children) {
const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
this.flatTreeData.splice(newIndex, 0, oldData)
if (newIndex > oldIndex) {
// 有子元素的,子元素需要同样跟上来
const flatChildren = []
this.getFlatNode(relatedRow.children || [], flatChildren)
if (flatChildren.length > 0) {
for (let i = 1, len = flatChildren.length; i <= len; i++) {
const childData = this.flatTreeData.splice(newIndex + i, 1)[0]
this.flatTreeData.splice(newIndex + i - 1, 0, childData)
}
}
}
}
// drag有, relate有
if (dragRow.children && relatedRow.children) {
if (newIndex < oldIndex) {
const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
this.flatTreeData.splice(newIndex, 0, oldData)
// 有子元素的,子元素需要同样跟上来
const flatChildren = []
this.getFlatNode(oldData.children || [], flatChildren)
if (flatChildren.length > 0) {
for (let i = 1, len = flatChildren.length; i <= len; i++) {
const childData = this.flatTreeData.splice(oldIndex + i, 1)[0]
this.flatTreeData.splice(newIndex + i, 0, childData)
}
}
} else {
const oldData = this.flatTreeData.splice(oldIndex, 1)[0]
// relateRow的children数
const relateFlatChildren = []
this.getFlatNode(relatedRow.children || [], relateFlatChildren)
this.flatTreeData.splice(newIndex + relateFlatChildren.length, 0, oldData)
// 有子元素的,子元素需要同样跟下来
const flatChildren = []
this.getFlatNode(oldData.children || [], flatChildren)
if (flatChildren.length > 0) {
for (let i = 1, len = flatChildren.length; i <= len; i++) {
const childData = this.flatTreeData.splice(oldIndex, 1)[0]
this.flatTreeData.splice(newIndex + relateFlatChildren.length, 0, childData)
}
}
}
}
// 重新生成树的数据
const data = this.getTreeData(this.flatTreeData, [])
console.log('this.flatTreeData', this.flatTreeData, data)
// 页面重新渲染
this.reRender(data, 'treeTableData')
}
}
})
},
getFlatNode(nodes, flatList, childrenKey = 'children') {
nodes.forEach(node => {
flatList.push(node)
if (node[childrenKey] && node[childrenKey].length) {
this.getFlatNode(node[childrenKey], flatList)
}
})
},
getTreeData(nodes, resultList) {
const childStack = []
let lastNode = {}
nodes.forEach(node => {
delete node.children
const pushNode = dataNode => {
const parentNode = childStack[childStack.length - 1]
if (parentNode) {
parentNode.children.push(dataNode)
} else {
resultList.push(dataNode)
}
}
if (node.level < lastNode.level) {
childStack.length = node.level - 1
pushNode(node)
} else if (node.level === lastNode.level) {
pushNode(node)
} else if (node.level > lastNode.level) {
if (!lastNode.children) {
lastNode.children = []
}
childStack.push(lastNode)
pushNode(node)
} else {
resultList.push(node)
}
lastNode = node
})
return resultList
},
reRender(data, dataKey) {
if (data) {
this[dataKey] = []
this.$nextTick(() => {
this[dataKey] = data
})
} else {
const origin = [].concat(this[dataKey])
this[dataKey] = []
this.$nextTick(() => {
this[dataKey] = origin
})
}
},
transverseNode(nodes, level = 1, cb, parentNode, childKey = 'children') {
nodes.forEach(node => {
if (node[childKey] && node[childKey].length > 0) {
this.transverseNode(node[childKey], level + 1, cb, node, childKey)
}
cb(node, level, parentNode)
})
return nodes
},
treeTableExpandChange(row, expanded) {
if (expanded) {
this.treeTableExpandKeys.push(row.id)
} else {
const idx = this.treeTableExpandKeys.indexOf(row.id)
this.treeTableExpandKeys.splice(idx, 1)
}
}
}
}
</script>
<style scoped lang="scss">
.home {
.body {
width: 890px;
height: 500px;
border: #ff3366 solid 10px;
box-sizing: border-box;
padding: 20px;
box-sizing: border-box;
}
}
.handle {
cursor: move;
display: flex;
align-content: center;
}
</style>