item 1
item 2
item 3
item 4
item 5
[ { "name": "item 1", "children": [ { "name": "item 2", "children": [] } ] }, { "name": "item 3", "children": [ { "name": "item 4", "children": [] } ] }, { "name": "item 5", "children": [] } ]
Use Components
We can use recursive components to achieve nested effects
When using this feature, please note: When using nested components, the recursive component name should be consistent with the component name. It is recommended to use defineOptions({name:'ComponentName'}).
TIP
This chapter uses the custom two-way binding method. If you don’t know much about it, please refer to the information on custom two-way binding first. vue2
and vue3
are different.
item 1
item 2
item 3
item 4
item 5
[ { "name": "item 1", "children": [ { "name": "item 2", "children": [] } ] }, { "name": "item 3", "children": [ { "name": "item 4", "children": [] } ] }, { "name": "item 5", "children": [] } ]
<template>
<div class="flex justify-between">
<nested-draggable v-model="list" class="w-full"></nested-draggable>
<preview-list :list="list" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import NestedDraggable from './NestedComponent.vue'
const list = ref([
{
name: 'item 1',
children: [
{
name: 'item 2',
children: []
}
]
},
{
name: 'item 3',
children: [
{
name: 'item 4',
children: []
}
]
},
{
name: 'item 5',
children: []
}
])
</script>
<template>
<VueDraggable class="drag-area" tag="ul" v-model="list" group="g1">
<li v-for="el in modelValue" :key="el.name">
<p>{{ el.name }}</p>
<nested-component v-model="el.children" />
</li>
</VueDraggable>
</template>
<script setup lang="ts">
import { VueDraggable } from 'vue-draggable-plus'
import { computed } from 'vue'
interface IList {
name: string
children: IList[]
}
interface Props {
modelValue: IList[]
}
const props = defineProps<Props>()
interface Emits {
(e: 'update:modelValue', value: IList[]): void
}
const emits = defineEmits<Emits>()
const list = computed({
get: () => props.modelValue,
set: value => emits('update:modelValue', value)
})
</script>
<style scoped>
.drag-area {
min-height: 50px;
outline: 1px dashed;
}
</style>
item 1
item 2
item 3
item 4
item 5
[ { "name": "item 1", "children": [ { "name": "item 2", "children": [] } ] }, { "name": "item 3", "children": [ { "name": "item 4", "children": [] } ] }, { "name": "item 5", "children": [] } ]
<template>
<div class="flex justify-between">
<NestedFunction v-model="list" class="w-full"></NestedFunction>
<preview-list :list="list" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import NestedFunction from './NestedFunction.vue'
const list = ref([
{
name: 'item 1',
children: [
{
name: 'item 2',
children: []
}
]
},
{
name: 'item 3',
children: [
{
name: 'item 4',
children: []
}
]
},
{
name: 'item 5',
children: []
}
])
</script>
<template>
<ul class="drag-area" ref="el">
<li v-for="el in modelValue" :key="el.name">
<p>{{ el.name }}</p>
<nested-function v-model="el.children" />
</li>
</ul>
</template>
<script setup lang="ts">
import { useDraggable } from 'vue-draggable-plus'
import { computed, ref } from 'vue'
interface IList {
name: string
children: IList[]
}
interface Props {
modelValue: IList[]
}
const props = defineProps<Props>()
interface Emits {
(e: 'update:modelValue', value: IList[]): void
}
const emits = defineEmits<Emits>()
const list = computed({
get: () => props.modelValue,
set: value => emits('update:modelValue', value)
})
const el = ref()
useDraggable(el, list, {
group: 'g1'
})
</script>
<style scoped>
.drag-area {
min-height: 50px;
outline: 1px dashed;
}
</style>
item 1
item 2
item 3
item 4
item 5
[ { "name": "item 1", "children": [ { "name": "item 2", "children": [] } ] }, { "name": "item 3", "children": [ { "name": "item 4", "children": [] } ] }, { "name": "item 5", "children": [] } ]
<template>
<div class="flex justify-between">
<NestedDirective v-model="list" class="w-full"></NestedDirective>
<preview-list :list="list" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import NestedDirective from './NestedDirective.vue'
const list = ref([
{
name: 'item 1',
children: [
{
name: 'item 2',
children: []
}
]
},
{
name: 'item 3',
children: [
{
name: 'item 4',
children: []
}
]
},
{
name: 'item 5',
children: []
}
])
</script>
<template>
<ul v-draggable="[list, { group: 'g1' }]" class="drag-area">
<li v-for="el in modelValue" :key="el.name">
<p>{{ el.name }}</p>
<nested-directive v-model="el.children" />
</li>
</ul>
</template>
<script setup lang="ts">
import { vDraggable } from 'vue-draggable-plus'
import { computed } from 'vue'
interface IList {
name: string
children: IList[]
}
interface Props {
modelValue: IList[]
}
const props = defineProps<Props>()
interface Emits {
(e: 'update:modelValue', value: IList[]): void
}
const emits = defineEmits<Emits>()
const list = computed({
get: () => props.modelValue,
set: value => emits('update:modelValue', value)
})
</script>
<style scoped>
.drag-area {
min-height: 50px;
outline: 1px dashed;
}
</style>