Using H5 draggable=”true” can achieve drag, but if it is used in VUE, we need to encapsulate, although it is not difficult, but there are mature wheels why not?

Drag and drop in vue can be implemented using VueDraggable.

There are a lot of articles on the use of VUe2, but the use of VUe3 is still relatively small, which is demonstrated here

Plugin repository address: vuedraggable

1, install,

yarn add vuedraggable@next
# or
npm i -S vuedraggable@next
Copy the code

2, use,

import draggable from 'vuedraggable'
Copy the code

Key points:

  1. Use the

    tag

  2. Attribute V-model =”List” The List is an array, usually corresponding to the actual data. Sorting, dragging and dropping actually change the value or order of the List.

  3. Attribute item-key=”key” This key is the key of each draggable component and requires a key for each data item in the List array to uniquely identify the child component.

  4. Attribute group. If you want drag and drop between containers, their group names should be the same, for example: group= ‘people’.

    But there are several attributes:

    Name: group name

    When you pull

    When you put something

    For example,

    :group="{ name: 'course', pull: 'clone', put: true }"
    Copy the code
  5. Attribute tag render

    , such as tag = ‘span’, then

    will become


  6. Start events, add, remove, update, the end, choose, unchoose, sort, filter, clone

  7. See the official documentation for more…

Example 3,

3.1 Drag and drop sort

<template>
  <div class="like">
    <! -- likeList specifies a key in the item-key list -->
    <draggable v-model="likeList" item-key="id">
      <template #item="{ element }">
        <div class="item">{{element.id + ", "+ element.name}}</div>
      </template>
    </draggable>
  </div>

  {{ likeList }}
</template>
<script>
import { defineComponent, ref } from "vue";

/ / introduce vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    // 需要使用ref
    const likeList = ref([
      { id: 1.name: "Fundamentals of Java Programming" },
      { id: 2.name: "Data Structures and Algorithms" },
      { id: 3.name: "Database Principles" },
      { id: 4.name: "Software Engineering"},]);return{ likeList }; }});</script>
<style>
.item {
  margin: 10px;
  padding: 10px;
  background: #ffffff;
}

.like {
  background: #fbc531;
  margin-bottom: 10px;
  padding: 10px;
  height: 300px;
}
</style>
Copy the code

3.2 Data Movement

<template>
  <div class="like">
    <! -- Add group attribute to drag and drop between two containers
    <draggable v-model="likeList" item-key="id" group="course">
      <template #item="{ element }">
        <div class="item">{{element.id + ", "+ element.name}}</div>
      </template>
    </draggable>
  </div>

  <div class="unlike">
    <draggable v-model="unlikeList" item-key="id" group="course">
      <template #item="{ element }">
        <div class="item">{{element.id + ", "+ element.name}}</div>
      </template>
    </draggable>
  </div>

  {{ likeList }}
  <hr />
  {{ unlikeList }}
</template>
<script>
import { defineComponent, ref } from "vue";

/ / introduce vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    // 需要使用ref
    const likeList = ref([
      { id: 1.name: "Fundamentals of Java Programming" },
      { id: 2.name: "Data Structures and Algorithms" },
      { id: 3.name: "Database Principles" },
      { id: 4.name: "Software Engineering"},]);const unlikeList = ref([
      { id: 5.name: "Financial Management" },
      { id: 6.name: "Accounting" },
      { id: 7.name: "Human Resource Management" },
      { id: 8.name: "Business Management"},]);return{ likeList, unlikeList }; }});</script>
<style lang="less">
.item {
  margin: 10px;
  padding: 10px;
  background: #ffffff;
}

.like {
  background: #fbc531;
  margin-bottom: 10px;
  padding: 10px;
  height: 300px;
}

.unlike {
  background: #353b48;
  margin-bottom: 10px;
  padding: 10px;
  height: 300px;
}
</style>
Copy the code

3.3 Data Cloning

Sometimes when we drag, we don’t want to affect the original data.

<template>
  <div class="like">
    <! -- add group attribute and configure pull: 'clone' -->
    <draggable
      v-model="likeList"
      item-key="id"
      :group="{ name: 'course', pull: 'clone' }"
    >
      <template #item="{ element }">
        <div class="item">{{element.id + ", "+ element.name}}</div>
      </template>
    </draggable>
  </div>

  <div class="unlike">
    <draggable
      v-model="unlikeList"
      item-key="id"
      :group="{ name: 'course', pull: 'clone' }"
    >
      <template #item="{ element }">
        <div class="item">{{element.id + ", "+ element.name}}</div>
      </template>
    </draggable>
  </div>

  {{ likeList }}
  <hr />
  {{ unlikeList }}
</template>
<script>
import { defineComponent, ref } from "vue";

/ / introduce vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    // 需要使用ref
    const likeList = ref([
      { id: 1.name: "Fundamentals of Java Programming" },
      { id: 2.name: "Data Structures and Algorithms" },
      { id: 3.name: "Database Principles" },
      { id: 4.name: "Software Engineering" },
      { id: 5.name: "Financial Management" },
      { id: 6.name: "Accounting" },
      { id: 7.name: "Human Resource Management"},]);const unlikeList = ref([{ id: 8.name: "Business Management" }]);
    return{ likeList, unlikeList }; }});</script>
<style">
.item {
  margin: 10px;
  padding: 10px;
  background: #ffffff;
}

.like {
  background: #fbc531;
  margin-bottom: 10px;
  padding: 10px;
}

.unlike {
  background: #353b48;
  margin-bottom: 10px;
  padding: 10px;
}
</style>
Copy the code

3.4 Cooperating with the component library

Form drag and drop?

Here we use ant-design-vue as an example. How to install it without demonstrating it? See next.antdv.com

Here I create two components, one for the List of components and one for the container Content to be placed.

The List:

<template> <! -- pull:'clone'.put: falseDrag and drop is a clone, cannot be placed in the component list, so as not to affect the original component list --><draggable
    v-model="componentList"
    item-key="id"
    :group="{ name: 'component', pull: 'clone', put: false }"
  >
    <template #item="{ element }">
      <div class="item">
        {{ element.tag }}
      </div>
    </template>
  </draggable>
</template>
<script>
import { defineComponent, ref } from "vue";

/ / introduce vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  name: "Lsit".components: {
    draggable,
  },
  setup() {
    // List of component data
    const componentList = ref([
      {
        id: 1.tag: "a-button".props: {
          type: "primary",}}, {id: 2.tag: "a-empty".props: {
          description: "No data pinch",}}, {id: 3.tag: "a-spin",}]);return{ componentList, }; }});</script>
<style>
.item {
  border: #0083ee 1px solid;
  margin: 10px;
  padding: 10px;
}
</style>
Copy the code

Content:

<template>
  <draggable
    v-model="componentList"
    item-key="id"
    class="content"
    :group="{ name: 'component' }"
  >
    <! After the component is clicked, change the style to active state -->
    <template #item="{ element }">
      <div
        :class="avtive == element.tag ? 'item-content active' : 'item-content'"
        @click="avtive = element.tag"
      >
        <! Vue dynamic components need to bind an IS to specify the tag name. Use v-bind to the component properties (pass in an object) v-on to bind the component events.
        <component
          :is="element.tag"
          v-bind="element.props"
          v-on="element.event"
          >{{ element.tag == "a-button" ? "a-button" : "" }}</component
        >
      </div>
    </template>
  </draggable>
</template>
<script>
import { defineComponent, ref } from "vue";

/ / introduce vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    const avtive = ref("");
    // 需要使用ref
    const componentList = ref([]);
    return{ avtive, componentList }; }});</script>
<style>
.content {
  height: 100%;
}

.item-content {
  margin: 10px;
}

.active {
  padding: 10px;
  border: springgreen 1px solid;
}
</style>
Copy the code

App:

<template>
  <a-layout class="main">
    <a-layout>
      <a-layout-sider style="margin-right: 8px">
        <List />
      </a-layout-sider>
      <a-layout-content class="content">
        <Content />
      </a-layout-content>
    </a-layout>
  </a-layout>
</template>
<script lang='ts'>
import { defineComponent } from "vue";

import List from "@components/List.vue";
import Content from "@components/Content.vue";

export default defineComponent({
  name: "App".components: {
    List,
    Content,
  },
  setup(){}});</script>
<style lang="less">
.main {
  height: 100vh;
}
.content {
  background: #ffffff;
}
.ant-layout-sider {
  background: #ffffff ! important;
}
</style>

Copy the code

4, summarize

Whether it’s drag and drop sorting, data movement, or component generation, drag and drop is an easier way to interact, and it’s all about what you see, what you get, and it’s getting lazier and lazier, which is why so many form designers are popping up.

Do not repeat the wheel, if the attitude is to learn, you can write a wheel, but if it is in the project, if there is a ready-made wheel, and very stable, can meet your needs, why not?