效果图
依赖安装
npm i sortablejs -S
<template>
<div class="warp">
<div class="parent-box" v-for="pItem in sortData" :key="pItem.name">
<h2 class="parent-name">{{ pItem.name }}</h2>
<div class="child-list" >
<div class="child-box" v-for="(cItem, cIndex) in pItem.children" :key="cItem.name" :data-id="cIndex">
<div class="child-name">{{ cItem.name }}</div>
</div>
</div>
</div>
</div>
<br>
<div>
<div> {{ sortData[0].name }}</div>
<br>
<div> {{ sortData[0].children }}</div>
</div>
<br>
<div>
<div> {{ sortData[1].name }}</div>
<br>
<div> {{ sortData[1].children }}</div>
</div>
<br>
<div>
<div> {{ sortData[2].name }}</div>
<br>
<div> {{ sortData[2].children }}</div>
</div>
</template>
<script setup lang="ts">
import Sortable from 'sortablejs'
import { ref, onMounted, nextTick } from 'vue'
interface DropEndType {
newIndex: number
oldIndex: number
}
interface ParentDropEndType extends DropEndType {
item: { closest: (arg0: string) => Element }
}
const sortData = ref([
{
name: 'Parent 1',
children: [
{ name: 'child 1 - P1' },
{ name: 'child 2 - P1' },
{ name: 'child 3 - P1' },
{ name: 'child 4 - P1' }
]
},
{
name: 'Parent 2',
children: [
{ name: 'child 1 - P2' },
{ name: 'child 2 - P2' },
{ name: 'child 3 - P2' },
{ name: 'child 4 - P2' }
]
},
{
name: 'Parent 3',
children: [
{ name: 'child 1 - P3' },
{ name: 'child 2 - P3' },
{ name: 'child 3 - P3' },
{ name: 'child 4 - P3' }
]
}
])
onMounted(() => {
const parentContainers = document.querySelectorAll('.parent-box')
parentContainers.forEach((container, index) => {
new Sortable(container.querySelector('.child-list'), {
group: `parent-${index}`,
sort: true,
animation: 150,
ghostClass: 'sortable-ghost',
onEnd: (e:ParentDropEndType) => {
nextTick(() => {
const allParentDom = document.querySelectorAll('.parent-box')
const parentIndex = Array.from(allParentDom).indexOf(e.item.closest('.parent-box'))
const childIndex = e.newIndex
const targetRow = sortData.value[parentIndex].children.splice(e.oldIndex, 1)[0]
sortData.value[parentIndex].children.splice(childIndex, 0, targetRow)
console.log(sortData.value)
})
}
})
})
new Sortable(document.querySelector('.warp'), {
group: 'parent',
sort: true,
animation: 300,
ghostClass: 'sortable-ghost',
onEnd: (e:DropEndType) => {
nextTick(() => {
const targetRow = sortData.value.splice(e.oldIndex, 1)[0]
sortData.value.splice(e.newIndex, 0, targetRow)
console.log(sortData.value)
})
}
})
})
</script>
<style lang="scss" scoped>
h2 {
margin: 0;
}
.warp {
background-color: #fff;
margin-top: 20px;
line-height: 1;
.parent-name {
padding: 10px;
background-color: #ddd;
margin-top: 20px;
cursor: move;
}
.child-list {
.child-name {
background-color: #f4f1f1;
padding: 15px 20px;
margin-top: 5px;
cursor: move;
}
}
}
</style>
如果需要ts
npm i --save-dev @types/sortablejs