实现低代码平台的拖拽效果

1.使用html5标签的dragstart、dragover、dragend实现一个简单的拖拽效果

vue3测试代码如下:

<template>
  <div>
    <div class="list">
      <!-- draggable 属性是HTML5中的一个属性,它用于定义元素是否可以被拖动,
        dragstart当用户开始拖动可拖动元素时触发,
        dragover当拖动元素进入潜在的拖放目标区域时触发,
        dragend当拖动操作完成,拖动元素被放置或取消拖动时触发-->
      <div class="item" v-for="(item, index) in list" :key="item.id" :draggable="true" @dragstart="onDragStart(index)"
        @dragover="onDragOver(index)" @dragend="onDragEnd">
        {{ item.name }}
      </div>
    </div>
    <pre class="data">{{ list }}</pre>
  </div>
</template>

<script setup >
import { ref } from 'vue'

// 记录拖拽的那个元素索引
const activeIndex = ref(null)
// 列表数据
const list = ref([
  { id: 3, name: '张三' },
  { id: 4, name: '李四' },
  { id: 5, name: '王五' },
  { id: 6, name: '赵六' },
  { id: 7, name: '田七' },
])

// 拖拽开始
const onDragStart = (index) => {
  // 更新下标
  activeIndex.value = index
}

//拖拽中
const onDragOver = (index) => {
  // 提取数据
  const draggingItem = list.value.splice(activeIndex.value, 1)
  // 添加数据
  list.value.splice(index, 0, ...draggingItem)
  // 更新下标
  activeIndex.value = index
}

//拖拽结束
const onDragEnd = () => {
  // 恢复下标
  activeIndex.value = null
}
</script>

<style lang="scss" scoped>
.list {
  width: 500px;
  border: 1px solid #000;

  .item {
    box-sizing: border-box;
    width: 100%;
    height: 40px;
    display: flex;
    justify-content: center;
    align-items: center;

    // 隔行变色
    &:nth-child(even) {
      background: #32a441;
    }

    &:nth-child(odd) {
      background: rgb(218, 11, 46);
    }
  }
}

.data {
  box-sizing: border-box;
  padding: 20px;
  width: 500px;
  border: 1px solid #000;
  font-family: serif;
}
</style>

效果如下:

2. 使用插件vuedraggable@next实现一个简单的拖拽效果

 安装依赖 npm i vuedraggable@next 

 使用 draggable 组件

vue3测试代码如下:

<template>
  <div>
    <draggable class="list" v-model="list" item-key="id">
      <template #item="{ element }">
        <div class="item">{{ element.name }}</div>
      </template>
    </draggable>
    <pre class="data">{{ list }}</pre>
  </div>
</template>

<script setup >
import { ref } from 'vue'
import draggable from 'vuedraggable'

// 列表数据
const list = ref([
  { id: 3, name: '张三' },
  { id: 4, name: '李四' },
  { id: 5, name: '王五' },
  { id: 6, name: '赵六' },
  { id: 7, name: '田七' },
])
</script>

<style lang="scss" scoped>
.list {
  width: 500px;
  border: 1px solid #000;

  .item {
    box-sizing: border-box;
    width: 100%;
    height: 40px;
    display: flex;
    justify-content: center;
    align-items: center;

    // 隔行变色
    &:nth-child(even) {
      background: #1fe63a;
    }

    &:nth-child(odd) {
      background: rgb(207, 28, 58);
    }
  }
}

.data {
  box-sizing: border-box;
  padding: 20px;
  width: 500px;
  border: 1px solid #000;
  font-family: serif;
}
</style>

3.使用插件vuedraggable@next实现两个列表之间相互拖拽

与第二点不同的是加个group属性,使用相同的name

vue3测试代码如下:

<template>
  <div>
    <!-- :group="{ name: 'task' }" 编组 -->
    <div class="group">
      <draggable class="list" v-model="list" item-key="id" :group="{ name: 'task' }">
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>

      <draggable class="list" v-model="list2" item-key="id" :group="{ name: 'task' }">
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
    <div class="group">
      <pre class="data">{{ list }}</pre>
      <pre class="data">{{ list2 }}</pre>
    </div>
  </div>
</template>

<script setup >
import { ref } from 'vue'
import draggable from 'vuedraggable'

// 任务分配,需要对任务实现编组

// 列表数据
const list = ref([
  { id: 3, name: '开发任务A' },
  { id: 4, name: '开发任务B' },
  { id: 5, name: '开发任务C' },
  { id: 6, name: '开发任务D' },
  { id: 7, name: '开发任务E' },
])

const list2 = ref([
  { id: 11, name: '工作1' },
  { id: 12, name: '工作2' },
  { id: 13, name: '工作3' },
])
</script>

<style lang="scss" scoped>
.group {
  display: flex;
}

.list {
  width: 500px;
  border: 1px solid #000;
  margin: 30px;

  .item {
    box-sizing: border-box;
    width: 100%;
    height: 40px;
    display: flex;
    justify-content: center;
    align-items: center;

    // 隔行变色
    &:nth-child(even) {
      background: #1fe63a;
    }

    &:nth-child(odd) {
      background: rgb(207, 28, 58);
    }
  }
}

.data {
  box-sizing: border-box;
  padding: 20px;
  width: 500px;
  border: 1px solid #000;
  font-family: serif;
  margin: 30px;
}
</style>

 实现效果如下(开发任务与工作可以相互拖拽):

4.使用插件vuedraggable@next实现低代码拖拽效果

(1) 没有安装element-plus先安装npm i element-plus

(2) main.js再引入:

// main.js
import { createApp } from 'vue'
import App from './App.vue'
// 导入组件库
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)   // 使用组件库
app.mount('#app')

vue3测试代码如下:

<script setup >
import { ref } from 'vue'
import draggable from 'vuedraggable'

// 需要使用ref
const list1 = ref([
  {
    id: 1,
    tag: 'el-button',
    props: {
      type: 'primary'
    },
    text: '按钮'
  },
  {
    id: 2,
    tag: 'el-input',
    props: {
      placeholder: '请输入内容'
    }
  },
  {
    id: 3,
    tag: 'el-switch'
  }
])

// 组件数据列表
const list2 = ref([])
</script>

<template>
  <el-container class="container">
    <el-aside class="aside" width="200px">
      <draggable class="list" v-model="list1" item-key="id" :group="{ name: 'component', pull: 'clone', put: false }"
        :sort="false">
        <template #item="{ element }">
          <div class="item">
            {{ element.tag }}
          </div>
        </template>
      </draggable>
    </el-aside>
    <el-main class="main">
      <draggable v-model="list2" item-key="id" class="content" :group="{ name: 'component' }">
        <template #item="{ element }">
          <div class="component">
            <!-- 
              is: 组件名
              v-bind: 动态 props
            -->
            <component :is="element.tag" v-bind="element.props">
              {{ element.text }}
            </component>
          </div>
        </template>
      </draggable>
    </el-main>
  </el-container>
</template>

<style scoped lang="scss">
.container {
  display: flex;
}

.aside {
  background-color: pink;
}

.main {
  flex: 1;
  height: 100vh;
  background-color: skyblue;

  .content {
    background-color: #fff;
    height: 100%;
  }
}

.list {
  .item {
    border: #0083ee 1px solid;
    margin: 10px;
    padding: 10px;
  }
}
</style>

实现效果如下:

一些常见配置的详解:v-model与item-key必填,其他非必填

属性说明
v-model用于绑定拖动列表的数据。通常是一个数组,其中包含要显示和拖动的元素列表。必填

item-key

每个元素唯一的标识,建议使用id。必填
group

控制拖动元素的分组,可以传字符型、数组、对象。一般传对象比较灵活。

字符串:使用相同分组标识符的元素将属于同一分组,可以相互拖动。如<vuedraggable group="group1">

数组:将多个分组标识符存储在数组中,从而使一个元素可以属于多个分组。如:<vuedraggable :group="['group1', 'group2']">"group1" 和 "group2" 分组,允许它与这两个分组中的元素互相拖动。

对象:传递包含更多配置信息的对象。对象可包含的属性。

   name:分组的名称,与字符串相同。

   pull:指定是否允许从分组中拖出元素,可以是 "clone"(可以克隆)、"move"(允许移动) 或 false(禁止从分组中拖出去)。

 put:指定是否允许将元素放置到分组中,可以是 "true" 或 false

disabled一个布尔值,用于禁用或启用拖动功能。
move

一个回调函数,拖动时所做的事情。该函数接受两个参数:事件对象和元素。<vuedraggable v-model="myList" :move="handleMove"></vuedraggable>

const handleMove = (event, element) => {

  console.log(event, element, '拖动')

}

start

一个回调函数,开始拖动时所做的事情。

<vuedraggable v-model="myList" : @start="onDragStart"></vuedraggable>

const onDragStart = (event) => {

  console.log(event, '开始')

}

end

一个回调函数,结束拖动时所做的事情。

<vuedraggable v-model="myList" : @end="handleEnd"></vuedraggable>

const handleEnd = (event) => {

  console.log(event, '结束')

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

更多详情查看官方文档:GitHub - SortableJS/vue.draggable.next: Vue 3 compatible drag-and-drop component based on Sortable.js 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值