添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

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

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

插件仓库地址: vuedraggable

yarn add vuedraggable@next
npm i -S vuedraggable@next
import draggable from 'vuedraggable'

使用<draggable>标签

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

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

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

但其中有几个属性:

name: 组名

pull 拖动的时候

put 放置的时候

:group="{ name: 'course', pull: 'clone', put: true }"

属性 tag 渲染后的<draggable>,例如tag =‘span’,那么<draggable>就会变为<span>

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

更多的请看官方文档...

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 }}
  {{ 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 }}
  {{ 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作为例子,如何安装不演示,请看官网:next.antdv.com

这里我创建两个组件,一个为组件列表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 }">
        :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>
<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>

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

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

分类:
前端
标签: