本示例基於Vue.Draggable中Nested示例,git地址:https://github.com/SortableJS/Vue.Draggable
需求描述
基於多表頭列表的一種后台設置:
1.列字段可以拖進表頭目錄中(文件與文件夾的關系)
2.可修改表頭目錄名稱
3.可刪除表頭目錄(刪除后目錄內部的列重排)
效果圖如下:

設置完成后在前台列表的展示:

代碼
1.nested-main.vue
<template>
<div class="row">
<div class="col-8">
<nested-draggable :tasks="list" />
</div>
<rawDisplayer
class="col-3"
:value="list"
title="List"
/>
</div>
</template>
<script>
import nestedDraggable from './infra/nested';
export default {
name: 'nested-main',
display: 'Nested',
order: 15,
components: {
nestedDraggable,
},
data() {
// 文件夾最后需要加一個{name:"",type:0,emptyHolder:true,tasks:[]}的空對象占位,否則無法拖進去
return {
list: [
{
name: 'task 1 文件夾',
type: 0,
tasks: [
{
name: 'task 2 文件',
type: 1,
tasks: []
},
{
name: '',
type: 0,
emptyHolder: true,
tasks: []
},
],
},
{
name: 'task 3 文件夾',
type: 0,
tasks: [
{
name: 'task 4 文件',
type: 1,
tasks: [],
},
{
name: '',
type: 0,
emptyHolder:true,
tasks: []
},
],
},
{
name: 'task 5 文件',
type: 1,
tasks: []
},
{
name: 'task 6 文件夾',
type: 0,
tasks: [
{
name: 'task 6-1 文件夾',
type: 0,
tasks: [
{
name: '',
type: 0,
emptyHolder:true,
tasks: []
},
],
},
{
name: '',
type: 0,
emptyHolder:true,
tasks: []
},
],
},
{
name: 'task 7 文件夾',
type: 0,
tasks: [
{
name: '',
type: 0,
emptyHolder:true,
tasks: []
},
],
}
],
};
},
};
</script>
<style scoped></style>
2.nested-draggable.vue
<template>
<div v-if="tasks&&tasks.length>0">
<draggable
class="dragArea"
tag="div"
v-bind="dragOptions"
:list="tasks"
:group="{ name: 'g1' }"
>
<template v-for="(el,index) in tasks">
<div
draggable=".item"
class="list-group-item"
:class="{'nested-1':el.type==0,'nested-2':el.type==1}"
v-if="!el.emptyHolder"
:key="index"
>
<p>{{ el.name }}</p>
<nested-draggable :tasks="el.tasks"></nested-draggable>
</div>
</template>
</draggable>
</div>
</template>
<script>
import draggable from '@/vuedraggable';
export default {
name: 'nested-draggable',
components: {
draggable,
},
computed: {
dragOptions() {
return {
group: 'nested',
ghostClass: 'ghost',
animation: 150,
fallbackOnBody: true,
swapThreshold: 0.65,
};
},
},
props: {
tasks: {
required: true,
type: Array,
},
},
methods: {
},
};
</script>
<style scoped>
.dragArea {
min-height: 50px;
outline: 1px dashed;
}
.list-group {
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
padding-left: 0;
margin-bottom: 0;
}
.list-group-item {
margin-top: 5px;
position: relative;
display: block;
padding: 0.75rem 1.25rem;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125);
}
.nested-1 {
background-color: #e6e6e6;
}
.nested-2 {
background-color: #cccccc;
}
.nested-3 {
background-color: #b3b3b3;
}
</style>
3.關於取值
每個文件夾最后都有一個冗余的對象{name: '',type: 0,emptyHolder:true,tasks: []}
我們可以通過emptyHolder:true屬性來進行過濾。
以下是遞歸的一種實現方式:
var f = item => { if (item['Children'] && item['Children'].length > 0) { item['Children'] = item['Children'].filter(f); return true; } else if (item.Type == 0 && item.emptyHolder) { return false; } else { return true; } }; const filterNestedProperty = this.nestedProperty.filter(f);
效果圖

