Vue 多层级目录拖动排序

本示例基于Vue.Draggable中Nested示例,git地址:https://github.com/SortableJS/Vue.Draggable

需求描述

基于多表头列表的一种后台设置:

1.列字段可以拖进表头目录中(文件与文件夹的关系)

2.可修改表头目录名称

3.可删除表头目录(删除后目录内部的列重排)

效果图如下:

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

image.png

代码

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);

效果图

原文地址:https://www.cnblogs.com/liaoshiqi/p/11428608.html