test:1.组件嵌套拖拽
2.schema定义与动态绑定
This commit is contained in:
22
src/components/ElTable.vue
Normal file
22
src/components/ElTable.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="el-table">
|
||||
<tr v-for="item in list" :key="item.name" class="cursor-move">
|
||||
<td>{{ item.id }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
list: Record<'name' | 'id', string>[]
|
||||
}
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 左侧组件列表 -->
|
||||
<div class="left">
|
||||
<div
|
||||
class="left-item"
|
||||
v-for="item in list1"
|
||||
:key="item.code"
|
||||
draggable
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 画布区域 -->
|
||||
<div class="targetContent" ref="targetContent">
|
||||
<div
|
||||
class="item"
|
||||
v-for="item in list2"
|
||||
:key="item.id"
|
||||
:ref="item.id"
|
||||
:style="{
|
||||
top: `${item.top - 16}px`,
|
||||
left: `${item.left - 85}px`,
|
||||
'z-index': `${item.zIndex}`
|
||||
}"
|
||||
>
|
||||
<template v-if="item.code === 'MyInput'">
|
||||
<a-input></a-input>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<div style="background: lightgreen; height: 100%; padding: 10px;">
|
||||
组件2内容
|
||||
<div v-if="$slots.default" class="slot-area">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MyComponent2'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.slot-area {
|
||||
border: 2px dashed grey;
|
||||
min-height: 50px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<div style="background: lightcoral; height: 100%; padding: 10px;">
|
||||
组件3内容
|
||||
<div v-if="$slots.default" class="slot-area">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MyComponent3'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.slot-area {
|
||||
border: 2px dashed grey;
|
||||
min-height: 50px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
37
src/components/NestedDirective.vue
Normal file
37
src/components/NestedDirective.vue
Normal file
@ -0,0 +1,37 @@
|
||||
<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>
|
||||
55
src/components/NestedFunction.vue
Normal file
55
src/components/NestedFunction.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<ul class="drag-area" ref="el">
|
||||
<li v-for="el in modelValue" :key="el.name">
|
||||
<div style="width: 200px;border: 1px solid red;">
|
||||
<p>{{ el.name }}:{{ el.id }}</p>
|
||||
</div>
|
||||
<nested-function v-model="el.children" />
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useDraggable} from 'vue-draggable-plus'
|
||||
import { computed, ref } from 'vue'
|
||||
import { IList } from '../type/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: 'designer',
|
||||
animation: 150,
|
||||
onStart() {
|
||||
console.log('start')
|
||||
},
|
||||
onUpdate() {
|
||||
console.log('update list1')
|
||||
},
|
||||
onAdd: (e) => {
|
||||
// console.log(e)
|
||||
console.log('add list1')
|
||||
},
|
||||
onRemove: () => {
|
||||
console.log('remove list1')
|
||||
}
|
||||
},)
|
||||
</script>
|
||||
<style scoped>
|
||||
.drag-area {
|
||||
min-height: 50px;
|
||||
outline: 1px dashed;
|
||||
background-color: hsl(0, 0%, 100%);
|
||||
}
|
||||
</style>
|
||||
@ -1,81 +1,75 @@
|
||||
<template>
|
||||
<div style="display: flex;">
|
||||
<section v-draggable="[
|
||||
list1,
|
||||
{
|
||||
animation: 150,
|
||||
group: {
|
||||
name: 'people',
|
||||
pull: 'clone',
|
||||
put: false
|
||||
},
|
||||
sort: false,
|
||||
clone
|
||||
}
|
||||
]">
|
||||
<div v-for="item in list1" :key="item.id" style="border: 1px solid green;margin: 5px;">
|
||||
{{ item.name }}
|
||||
<div style="display: flex;flex-direction: row;">
|
||||
<div ref="el2" style="margin: 5%;display: flex;flex-direction: column;">
|
||||
<div v-for="item in list1" :key="item.id" style="width: 200px;border: 1px solid red;">
|
||||
{{ item.name }}:{{ item.id }}
|
||||
</div>
|
||||
</section>
|
||||
<section v-draggable="[
|
||||
list2,
|
||||
{
|
||||
animation: 150,
|
||||
group: 'people'
|
||||
}
|
||||
]">
|
||||
<div v-for="item in list2" :key="item.id" style="border: 1px solid red;margin: 5px;">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
{{ list1 }}
|
||||
</div>
|
||||
<div>
|
||||
{{ list2 }}
|
||||
|
||||
<div class="flex justify-between">
|
||||
<NestedFunction v-model="list" class="w-full"></NestedFunction>
|
||||
{{ list }}
|
||||
</div>
|
||||
</br>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { uuid } from 'lsp-uuid'
|
||||
import { vDraggable } from 'vue-draggable-plus'
|
||||
import NestedFunction from './NestedFunction.vue'
|
||||
import { useDraggable } from 'vue-draggable-plus'
|
||||
import { uuid } from 'lsp-uuid';
|
||||
|
||||
|
||||
const list1 = ref([
|
||||
{
|
||||
name: 'Joao',
|
||||
id: '1'
|
||||
{
|
||||
type: 'Switch',
|
||||
name: '开关',
|
||||
id: 'switch',
|
||||
designer: '',
|
||||
props: {},
|
||||
style: '',
|
||||
class: '',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
name: 'Jean',
|
||||
id: '2'
|
||||
type: 'Rate',
|
||||
name: '开关',
|
||||
id: 'rate',
|
||||
designer: '',
|
||||
props: {},
|
||||
style: '',
|
||||
class: '',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
name: 'Johanna',
|
||||
id: '3'
|
||||
},
|
||||
{
|
||||
name: 'Juan',
|
||||
id: '4'
|
||||
type: 'Button',
|
||||
name: '按钮',
|
||||
id: 'button',
|
||||
designer: '',
|
||||
props: {},
|
||||
style: '',
|
||||
class: '',
|
||||
children: []
|
||||
}
|
||||
|
||||
])
|
||||
const list2 = ref(
|
||||
list1.value.map(item => ({
|
||||
name: `${item.name}-2`,
|
||||
id: `${item.id}-2`
|
||||
}))
|
||||
)
|
||||
const list=ref([])
|
||||
|
||||
function clone(element: Record<'name' | 'id', string>) {
|
||||
const len = list2.value.length
|
||||
return {
|
||||
name: `${element.name}-clone-${len}`,
|
||||
id: `${element.id}-clone-${uuid()}`
|
||||
const el2 = ref()
|
||||
|
||||
useDraggable(el2, list1, {
|
||||
animation: 150,
|
||||
group: { name: 'designer', pull: 'clone', put: false },
|
||||
sort: false,
|
||||
onClone() {
|
||||
console.log('clone')
|
||||
},
|
||||
clone(element: Record<'id'|'children', any>) {
|
||||
return {
|
||||
id: `${element.id}-${uuid()}`,
|
||||
children:[]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
10
src/type/IList.ts
Normal file
10
src/type/IList.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export interface IList {
|
||||
type: string;
|
||||
name: string;
|
||||
id: string;
|
||||
designer: JSON;
|
||||
props: JSON;
|
||||
style: string;
|
||||
class: string;
|
||||
children: IList[];
|
||||
}
|
||||
Reference in New Issue
Block a user