如何提高Vue可拖动嵌套的精度?

问题描述 投票:0回答:1

我一直在使用Vue 2组件和Vue.Draggable库开发表单构建器。除了一个持续存在的问题之外,此方法效果很好-对于最终用户而言,嵌套块实际上很难嵌套。要使一个块缩进另一个块,需要很多精度和反复试验。

如何解决此问题并使它更易于使用?似乎几乎是因为缺少拖放区。

[The issue demonstrated(由于无法嵌入动画图像,因此链接到Imgur)]

[请注意,由于多个文件的性质,我无法在CodePen中运行代码。该代码还依赖于UI的TailwindCSS。

/FormBuilder.vue

<style>
    .wrapper {
        margin-bottom: -1rem;
    }
    .group.templates {
        display: flex;
        flex-direction: row;
        margin: 0 -0.5em;
    }
    .group.templates .field {
        margin: 0 0.5rem;
    }
    .group.elements {
        margin-top: 1rem;
    }
    .group.elements .field {
        margin: 1rem 0;
    }
    .group.elements .field + div {
        margin-left: 1rem;
    }
    .group.elements .ghost {
        opacity: 0.5;
    }
</style>

<template>
    <div>
        <div>
            <draggable :list="templates" :group="{ name: 'form-builder', pull: 'clone', put: false }" :clone="cloneTemplate" :component-data="getComponentData()">
                <div v-for="element in templates" :key="element.name">
                    <div class="field bg-white rounded shadow rounded font-bold text-gray-700 px-4 py-2">
                        <h4 class="font-bold"><i class="fas mr-2" :class="[ 'fa-' + element.icon ]"></i> {{ element.name }}</h4>
                    </div>
                </div>
            </draggable>
        </div>
        <div class="wrapper">
            <nested-draggable :items="elements" name="form-builder"></nested-draggable>
        </div>
    </div>
</template>

<script>
    import Draggable from 'vuedraggable'
    import NestedDraggable from './FormBuilder/NestedDraggable'

    export default {
        components: {
            Draggable,
            NestedDraggable,
        },

        data() {
            return {
                id: 6,
                templates: [
                    {
                        name: 'Field',
                        icon: 'heading',
                        type: 'field'
                    }
                ],
                elements: [
                    {
                        id: 1,
                        type: 'test',
                        locked: true,
                        options: {
                            text: "field"
                        },
                        children: []
                    },
                    {
                        id: 2,
                        type: 'paragraph',
                        locked: false,
                        options: {
                            text: "field"
                        },
                        children: []
                    },
                    {
                        id: 3,
                        type: 'field',
                        locked: false,
                        options: {
                            text: "field"
                        },
                        children: [
                            {
                                id: 4,
                                type: 'field',
                                locked: false,
                                options: {
                                    text: "field"
                                },
                                children: []
                            },
                            {
                                id: 5,
                                type: 'field',
                                locked: false,
                                options: {
                                    text: "field"
                                },
                                children: []
                            }
                        ]
                    }
                ]
            }
        },

        methods: {
            cloneTemplate(object) {
                return {
                    id: this.id++,
                    type: object.type,
                    locked: false,
                    options: {},
                    children: []
                }
            },
            getComponentData() {
                return {
                    attrs: {
                        class: 'group templates'
                    }
                }
            }
        }
    }
</script>

/FormBuilder/NestedDraggable.vue

<template>
    <draggable ghost-class="ghost" :list="items" :group="name" :component-data="getComponentData()">
        <div v-for="element in items" :key="element.id">
            <field v-if="element.type == 'field'" :locked="element.locked" :options="element.options"></field>
            <nested-draggable v-if="element.children" :items="element.children" :name="name"></nested-draggable>
        </div>
    </draggable>
</template>

<script>
    import draggable from 'vuedraggable'

    import field from "./Fields/Field"

    export default {
        name: 'nested-draggable',

        components: {
            draggable,
            field
        },

        props: {
            name: {
                type: String,
                required: true
            },
            items: {
                type: Array,
                required: true
            }
        },

        methods: {
            getComponentData() {
                return {
                    attrs: {
                        class: 'group elements'
                    }
                }
            }
        }
    }
</script>

/FormBuilder/Fields/Field.vue

<template>
    <div class="field bg-white rounded shadow rounded">
        <div class="px-4 py-2 border-b flex flex-row items-center text-gray-700">
            <h4 class="font-bold mr-4"><i class="fas fa-heading mr-2"></i> Field</h4>
        </div>
        <div class="p-4 pt-2">
            <label for="content" class="form-label">Content</label>
            <input type="text" id="content" class="form-control">
        </div>
    </div>
</template>

<script>
    export default {
        props: {
            locked: {
                type: Boolean,
                default: false
            },
            options: {
                type: Object,
                default: () => {
                    return {
                        content: ''
                    }
                }
            }
        }
    }
</script>
javascript vue.js vuejs2 draggable vue.draggable
1个回答
0
投票

options道具可以做到。 Vue Draggable使用SortableJS。现在,它仍然通过options属性传递选项。

<template>
<draggable :options="{swapThreshold: 0.5}">
    <div v-for="element in items" :key="element.id">
        <field v-if="element.type == 'field'" :locked="element.locked" :options="element.options"></field>
        <nested-draggable v-if="element.children" :items="element.children" :name="name"></nested-draggable>
    </div>
</draggable>

在上面显示的示例中,我将阈值降低了一半。

https://github.com/SortableJS/Sortable#swapthreshold-option

swapThreshold选项

交换区域将占用的目标百分比,介于0和1之间的浮点数。

注意

option道具已弃用,在以后的版本中将被删除。我认为它是尚未实现的其他选项的后备选项,例如swapThreshold

有关已弃用通知的更多详细信息,请参见:https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#options-props

如果您想使用Vue Draggable文档中没有的其他选项,可以查看SortableJS的选项页面以查看仍然可以使用的选项:

https://github.com/SortableJS/Sortable#options

© www.soinside.com 2019 - 2024. All rights reserved.