1. 可拖拽元素及拖拽目标区域
1)可拖拽元素
<div class="drag-el" v-for="item of 8" :key="item" :draggable="true" @dragstart="dragstart($event, item)">{{ item }}</div>
需要注意一点的是:标签直接加draggable,如果元素是文本,需要选中之后才可以进行拖拽;而写成 :draggable="true" 则可以直接进行拖拽,无需选中
2)目标区域
<div class="drop-content" @dragover.prevent @drop="drop"></div>
目前个人理解的最简的写法
拖拽元素开始拖拽 -> 拖拽到目标区域 -> 松开鼠标(拖拽结束)
2. 拖拽过程涉及到的数据传输
开始拖拽时即可拖拽元素的dragstart方法,可以将数据存到event的数据传输对象里
// 开始拖拽
const dragstart = (e: any, data: any) => {
e.dataTransfer.setData('customData', data)
}
再拖拽结束时可以从event里获取传输的数据
// 鼠标松开事件
const drop = (e: any) => {
console.log(e.dataTransfer.getData('customData')) // 拖拽传输的数据
draggableData.value.push(e.dataTransfer.getData('customData'))
}
全部代码如下
<template>
<div class="drag-page">
<div class="drag-content">
<div class="dc-title">可拖拽区域</div>
<div class="dc-content">
<div class="dc-el" v-for="item of 8" :key="item" :draggable="true" @dragstart="dragstart($event, item)">{{ item }}</div>
</div>
</div>
<div class="drop-content" @dragover.prevent @drop="drop">
<div class="dpc-title">可移入区域</div>
<div class="dpc-content">
<div class="dpc-el" v-for="(item, index) in draggableData" :key="index" @dblclick="dblClick(index)">{{ item }}</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const draggableData = ref<any>([])
// 开始拖拽
const dragstart = (e: any, data: any) => {
e.dataTransfer.setData('customData', data)
}
// 鼠标松开事件
const drop = (e: any) => {
console.log(e.dataTransfer.getData('customData')) // 拖拽传输的数据
draggableData.value.push(e.dataTransfer.getData('customData'))
}
// 双击事件
const dblClick = (i: number) => {
draggableData.value.splice(i, 1)
}
</script>
<style lang="less" scoped>
.drag-page {
height: 100vh;
display: flex;
align-items: center;
.drag-content {
width: 250px;
height: 100%;
background: #ddd;
padding: 10px 15px;
.dc-title {
text-align: center;
}
.dc-content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.dc-el {
margin-top: 20px;
width: 100px;
height: 100px;
background: #ccc;
}
}
}
.drop-content {
flex: 1;
height: 100%;
background: #fff;
padding: 10px 15px;
.dpc-title {
text-align: center;
}
.dpc-content {
display: flex;
flex-wrap: wrap;
.dpc-el {
margin-top: 20px;
margin-left: 20px;
width: 100px;
height: 100px;
background: #ccc;
}
}
}
}
</style>