知海

自定义克隆

vue-draggable-plus指南-教程

自定义克隆

我们可以通过 clone 属性传递一个函数,来自定义克隆的节点。内部使用 JSON.parse(JSON.stringify()) 实现克隆,您也可以选择使用 lodash 或者其他第三方库的方式进行克隆。此功能常用于低代码场景,比如拖拽表单元素到画布中,需要克隆一个新的组件元素。

我们在使用该功能时,需要注意:

  1. 被克隆组件的 group 属性中的 pull 属性必须为 clone,否则无法克隆。
  2. 被克隆组件中的 group 中的 name 属性必须与克隆组件的 group 中的 name 属性一致,否则无法克隆。

💡 提示
注意:当我们使用 clone 属性时,需要重新生成一个唯一的 key,否则会导致组件渲染异常。

组件使用

vue 复制代码
<template>
  <div class="flex">
    <VueDraggable
      v-model="list1"
      :animation="150"
      ghostClass="ghost"
      :group="{ name: 'people', pull: 'clone', put: false }"
      :clone="clone"
      :sort="false"
      class="flex flex-col gap-2 p-4 w-300px bg-gray-500/5 rounded"
    >
      <div
        v-for="item in list1"
        :key="item.id"
        class="cursor-move h-50px bg-gray-500/5 rounded p-3"
      >
        {{ item.name }}
      </div>
    </VueDraggable>
    <VueDraggable
      v-model="list2"
      :animation="150"
      group="people"
      ghostClass="ghost"
      class="flex flex-col gap-2 p-4 w-300px max-h-350px m-auto bg-gray-500/5 rounded overflow-auto"
    >
      <div
        v-for="item in list2"
        :key="item.id"
        class="cursor-move h-50px bg-gray-500/5 rounded p-3"
      >
        {{ item.name }}
      </div>
    </VueDraggable>
  </div>
  <div class="flex justify-between">
    <preview-list :list="list1" />
    <preview-list :list="list2" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'

const list1 = ref([
  {
    name: 'Joao',
    id: '1'
  },
  {
    name: 'Jean',
    id: '2'
  },
  {
    name: 'Johanna',
    id: '3'
  },
  {
    name: 'Juan',
    id: '4'
  }
])
const list2 = ref(
  list1.value.map(item => ({
    name: `${item.name}-2`,
    id: `${item.id}-2`
  }))
)

function clone(element: Record<'name' | 'id', string>) {
  const len = list2.value.length
  return {
    name: `${element.name}-clone-${len}`,
    id: `${element.id}-clone-${len}`
  }
}
</script>

函数使用

vue 复制代码
<template>
  <div class="flex">
    <section
      class="flex flex-col gap-2 p-4 w-300px bg-gray-500/5 rounded"
      ref="el1"
    >
      <div
        v-for="item in list1"
        :key="item.id"
        class="cursor-move h-50px bg-gray-500/5 rounded p-3"
      >
        {{ item.name }}
      </div>
    </section>
    <section
      class="flex flex-col gap-2 p-4 w-300px max-h-350px m-auto bg-gray-500/5 rounded overflow-auto"
      ref="el2"
    >
      <div
        v-for="item in list2"
        :key="item.id"
        class="cursor-move h-50px bg-gray-500/5 rounded p-3"
      >
        {{ item.name }}
      </div>
    </section>
  </div>
  <div class="flex justify-between">
    <preview-list :list="list1" />
    <preview-list :list="list2" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useDraggable } from 'vue-draggable-plus'

const list1 = ref([
  {
    name: 'Joao',
    id: '1'
  },
  {
    name: 'Jean',
    id: '2'
  },
  {
    name: 'Johanna',
    id: '3'
  },
  {
    name: 'Juan',
    id: '4'
  }
])
const list2 = ref(
  list1.value.map(item => ({
    name: `${item.name}-2`,
    id: `${item.id}-2`
  }))
)

const el1 = ref()
const el2 = ref()
useDraggable(el1, list1, {
  animation: 150,
  group: {
    name: 'people',
    pull: 'clone',
    put: false
  },
  sort: false,
  clone(element: Record<'name' | 'id', string>) {
    const len = list2.value.length
    return {
      name: `${element.name}-clone-${len}`,
      id: `${element.id}-clone-${len}`
    }
  }
})
useDraggable(el2, list2, {
  animation: 150,
  group: 'people'
})
</script>

指令使用

vue 复制代码
<template>
  <div class="flex">
    <section
      class="flex flex-col gap-2 p-4 w-300px bg-gray-500/5 rounded"
      v-draggable="[
        list1,
        {
          animation: 150,
          group: {
            name: 'people',
            pull: 'clone',
            put: false
          },
          sort: false,
          clone
        }
      ]"
    >
      <div
        v-for="item in list1"
        :key="item.id"
        class="cursor-move h-50px bg-gray-500/5 rounded p-3"
      >
        {{ item.name }}
      </div>
    </section>
    <section
      class="flex flex-col gap-2 p-4 w-300px max-h-350px m-auto bg-gray-500/5 rounded overflow-auto"
      v-draggable="[
        list2,
        {
          animation: 150,
          group: 'people'
        }
      ]"
    >
      <div
        v-for="item in list2"
        :key="item.id"
        class="cursor-move h-50px bg-gray-500/5 rounded p-3"
      >
        {{ item.name }}
      </div>
    </section>
  </div>
  <div class="flex justify-between">
    <preview-list :list="list1" />
    <preview-list :list="list2" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { vDraggable } from 'vue-draggable-plus'

const list1 = ref([
  {
    name: 'Joao',
    id: '1'
  },
  {
    name: 'Jean',
    id: '2'
  },
  {
    name: 'Johanna',
    id: '3'
  },
  {
    name: 'Juan',
    id: '4'
  }
])
const list2 = ref(
  list1.value.map(item => ({
    name: `${item.name}-2`,
    id: `${item.id}-2`
  }))
)

function clone(element: Record<'name' | 'id', string>) {
  const len = list2.value.length
  return {
    name: `${element.name}-clone-${len}`,
    id: `${element.id}-clone-${len}`
  }
}
</script>

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。