vuedraggable实现组件拖拽,页面生成器?

使用H5的draggable="true"虽然可以实现拖拽,但如果是在vue中使用,我们需要去封装,虽然不难,但是有成熟的轮子为什么不用呢?

在vue中实现拖拽可以使用vuedraggable实现。

在vue2中的使用有一堆文章,但是在vue3中的使用还是比较少,这里使用vue3进行演示

插件仓库地址:vuedraggable

1、安装

yarn add vuedraggable@next
# 或者
npm i -S vuedraggable@next

2、使用

import draggable from 'vuedraggable'

关键点:

  1. 使用<draggable>标签

  2. 属性 v-model="List"这个List为一个数组,一般与实际数据对应。排序、拖拽实际上都是改变这个List的值或顺序。

  3. 属性 item-key="key" 这个key为每个可拖拽组件的key,要求List数组中的每个数据项中有一个key作为子组件的唯一标识。

  4. 属性 group 分组,如果要在不同容器间实现拖拽,那么它们的组名应该相等,例如:group=‘people’。

    但其中有几个属性:

    name: 组名

    pull 拖动的时候

    put 放置的时候

    例如

    :group="{ name: 'course', pull: 'clone', put: true }"
    
  5. 属性 tag 渲染后的<draggable>,例如tag =‘span’,那么<draggable>就会变为<span>

  6. 事件start,add,remove,update,end,choose,unchoose,sort,filter,clone

  7. 更多的请看官方文档

3、例子

3.1 拖拽排序

在这里插入图片描述

<template>
  <div class="like">
    <!-- 
      likeList数据列表
      item-key数据项中某个属性作为key
     -->
    <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";

// 引入vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    // 需要使用ref
    const likeList = ref([
      { id: 1, name: "java程序设计基础" },
      { id: 2, name: "数据结构与算法" },
      { id: 3, name: "数据库原理" },
      { id: 4, name: "软件工程" },
    ]);
    return { likeList };
  },
});
</script>
<style>
.item {
  margin: 10px;
  padding: 10px;
  background: #ffffff;
}

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

3.2数据移动

在上面的例子中再加一个数据列表,实现在两个容器中进行数据的拖动
在这里插入图片描述

<template>
  <div class="like">
    <!-- 
      注意需要加上group属性,才能在两个容器中进行拖拽
     -->
    <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";

// 引入vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    // 需要使用ref
    const likeList = ref([
      { id: 1, name: "java程序设计基础" },
      { id: 2, name: "数据结构与算法" },
      { id: 3, name: "数据库原理" },
      { id: 4, name: "软件工程" },
    ]);

    const unlikeList = ref([
      { id: 5, name: "财务管理" },
      { id: 6, name: "会计" },
      { id: 7, name: "人力资源管理" },
      { id: 8, name: "企业管理" },
    ]);
    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>

3.3 数据克隆

有时候我们拖动的时候并不想影响原来的数据。

在这里插入图片描述

<template>
  <div class="like">
    <!-- 
      注意需要加上group属性,并配置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";

// 引入vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    // 需要使用ref
    const likeList = ref([
      { id: 1, name: "java程序设计基础" },
      { id: 2, name: "数据结构与算法" },
      { id: 3, name: "数据库原理" },
      { id: 4, name: "软件工程" },
      { id: 5, name: "财务管理" },
      { id: 6, name: "会计" },
      { id: 7, name: "人力资源管理" },
    ]);

    const unlikeList = ref([{ id: 8, name: "企业管理" }]);
    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>

3.4 与组件库配合

表单拖拽?

这里以ant-design-vue作为例子,如何安装不演示,请看官网:https://next.antdv.com

4

这里我创建两个组件,一个为组件列表List,一个为待放置容器Content。

List:

<template>
  <!-- 
    pull: 'clone', put: false
    意思是以克隆的方式拖拽,,不能在组件列表进行放置,目的是不影响原来的组件列表
  -->
  <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";

// 引入vuedraggable
import draggable from "vuedraggable";

export default defineComponent({
  name: "Lsit",
  components: {
    draggable,
  },
  setup() {
    // 组件数据列表
    const componentList = ref([
      {
        id: 1,
        tag: "a-button",
        props: {
          type: "primary",
        },
      },
      {
        id: 2,
        tag: "a-empty",
        props: {
          description: "没有数据捏",
        },
      },
      {
        id: 3,
        tag: "a-spin",
      },
    ]);
    return {
      componentList,
    };
  },
});
</script>
<style>
.item {
  border: #0083ee 1px solid;
  margin: 10px;
  padding: 10px;
}
</style>

Content:

<template>
  <draggable
    v-model="componentList"
    item-key="id"
    class="content"
    :group="{ name: 'component' }"
  >
    <!-- 
      组件点击后,修改样式为激活状态
    -->
    <template #item="{ element }">
      <div
        :class="avtive == element.tag ? 'item-content active' : 'item-content'"
        @click="avtive = element.tag"
      >
        <!-- 
          使用vue的动态组件component 需要绑定一个is指明是哪个标签,is里面是标签名
          使用v-bind绑定这个组件的属性(传入一个对象即可)
          v-on使用v-on绑定这个组件对应的事件即可
         -->
        <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";

// 引入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>

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>

4、总结

不管是拖拽排序,数据移动,还是组件生成,拖拽都是一种更简单的交互方式,即托即见即所得,发展都是越来越懒的过程,这也是为什么现在很多的表单设计器井喷。

不要重复造轮子,如果是学习的态度,完全可以自己动手写一个,但是如果是在项目中,如果有现成的轮子,并且很稳定,能满足你的需要,为什么不用呢?

  • 8
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue3和Vue2一样都可以使用vuedraggable插件进行不同组件。以下是使用vuedraggable插件实现不同组件的步骤: 1. 安装vuedraggable插件 在终端中执行以下命令: ``` npm install vuedraggable ``` 2. 引入vuedraggable插件 在需要使用vuedraggable插件的组件中引入: ```javascript import draggable from 'vuedraggable' ``` 3. 使用draggable组件 在模板中使用draggable组件,并设置相应的属性: ```html <draggable v-model="list" :element="'ul'" :options="{group:'items'}"> <li v-for="(item, index) in list" :key="item.id">{{ item.name }}</li> </draggable> ``` 其中,v-model绑定了一个数组list,用于记录后的顺序;:element指定了的元素类型,这里为ul;:options指定了的选项,这里设置了group为items,表示不同的组件可以互相。 注意:v-model绑定的数组中的元素必须要有一个唯一的标识符,用于区分不同的元素。 4. 处理事件 当完成后,可以通过监听dragend事件来处理后的逻辑: ```html <draggable v-model="list" :element="'ul'" :options="{group:'items'}" @dragend="onDragEnd"> <li v-for="(item, index) in list" :key="item.id">{{ item.name }}</li> </draggable> ``` ```javascript methods: { onDragEnd(event) { console.log(event) // 处理完成后的逻辑 } } ``` 在onDragEnd方法中,可以获取到完成后的事件对象,通过事件对象可以获取到前后的元素顺序,从而进行相应的操作。 以上就是使用vuedraggable插件实现不同组件的步骤。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值