本贴 适用与vue2 , vuedraggable.js 版本 "vuedraggable": "^2.24.3"
由于js有原生的属性可以拖拽dom元素,需要在组件添加 ‘forceFallback="true"’ 这属性, 否则可能会导致页面组件不能拖拽,这个问题也分浏览器,
数据的拖拽原数据 与嵌套深度数据 之前的唯一 值, id 最好别冲突, 页面容易报错
vuedraggable.js 二次开发
第一步 在vue 2 中引入 vuedraggable.js
npm i -S vuedraggable
第二步 创建 home.vue 组件名称
第三步 复制下面代码
<template>
<div id="app">
<el-row :gutter="22">
<el-col :span="6" class="itxst">
<div class="title">车队</div>
<draggable v-model="catList" :group="cat" @start="originalStart($event, 1)" @sort="originalSort($event, 1)"
@end="originalEnd(1)" :disabled="catListShow" forceFallback="true" animation="1" dragClass="dragClass"
ghostClass="ghostClass" chosenClass="chosenClass" style="width: 180px">
<transition-group>
<div class="item" v-for="item in catList" :key="item.id">
{{ item.name }}
</div>
</transition-group>
</draggable>
<div class="title">司机名称</div>
<draggable v-model="driverList" :group="driver" @end="end($event, 2)" @add="add($event, 2)"
:disabled="driverListShow" @start="originalStart($event, 2)" forceFallback="true" animation="300"
dragClass="dragClass" ghostClass="ghostClass" chosenClass="chosenClass">
<transition-group>
<div class="item" v-for="item in driverList" :key="item.id">
{{ item.name }}
</div>
</transition-group>
</draggable>
<div class="title">班车路线</div>
<draggable v-model="lineList" :group="line" @end="end($event, 6)" @add="add($event, 6)" :disabled="lineListShow"
@start="originalStart($event, 6)" forceFallback="true" animation="300" dragClass="dragClass"
ghostClass="ghostClass" chosenClass="chosenClass">
<transition-group>
<div class="item" v-for="item in lineList" :key="item.id">
{{ item.name }}
</div>
</transition-group>
</draggable>
</el-col>
<el-col :span="18" class="itxst">
<div v-for="(item, index) in groupList" :key="index">
<div style="display: flex">
<div style="width: 20px; background: #2c3e50; color: #eeeeee">
{{ item.tripTxet }}
</div>
<!-- 移动表格-->
<draggable v-model="item.tripList" :group="tripListGroup" :disabled="tripListShow" forceFallback="true"
animation="300" style="width: 1200px; border: 1px solid yellow" @start="originalStart($event, 3)"
@end="end($event, 3)" @add="add($event, 3)" dragClass="dragClass" ghostClass="ghostClass"
chosenClass="chosenClass">
<transition-group style="display: flex; min-height: 250px">
<div style="width: 200px; padding: 20px; background: darkgoldenrod" v-for="items in item.tripList"
:key="items.id">
<div>{{ items.tripListTxet }}</div>
<!-- 车牌移动-->
<draggable v-model="items.catListTiem" :group="cat" @start="startSon(4, items, items.id)"
@sort="sortSon(4, items.id, items)" @end="endSon(4, items.id)" @add="addSon(4, items.id)"
:disabled="catListShow" forceFallback="true" style="min-height: 80px">
<transition-group style="height: 80px">
<div v-for="(itemk ,index) in items.catListTiem" :key="index">
<div class="item" style="color: chartreuse; background: black">
{{ itemk.name }}
</div>
<div class="item" style="color: chartreuse; background: black">
{{ itemk.catNum }}
</div>
</div>
</transition-group>
</draggable>
<!-- 司机移动-->
<draggable v-model="items.driverListTiem" :group="driver" @start="start(5, items)"
@end="end($event, 5, item.tripList)" @add="add($event, 5)" :disabled="driverListShow"
forceFallback="true" animation="300" dragClass="dragClass" ghostClass="ghostClass"
chosenClass="chosenClass">
<transition-group>
<div v-for="itemk in items.driverListTiem" :key="itemk.id">
<div class="item" style="
color: chartreuse;
height: 30px;
background: black;
">
{{ itemk.name }}
</div>
</div>
</transition-group>
</draggable>
<!-- 班车路线 -->
<draggable v-model="items.lineListTiem" :group="lineGroup" @start="start(7, items)"
@end="end($event, 7, item.tripList)" @add="add($event, 7)" :disabled="lineListShow"
forceFallback="true" animation="300" dragClass="dragClass" ghostClass="ghostClass"
chosenClass="chosenClass">
<transition-group>
<div v-for="itemj in items.lineListTiem" :key="itemj.id">
<div class="item" style="
color: chartreuse;
height: 30px;
background: black;
">
{{ itemj.name }}
</div>
</div>
</transition-group>
</draggable>
</div>
</transition-group>
</draggable>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
//导入draggable组件
import draggable from "vuedraggable";
export default {
//注册draggable组件
components: {
draggable,
},
data() {
return {
drag: false,
tripListShow: false, // 表格拖动
catListShow: false, // 车牌拖动
driverListShow: false, // 司机拖动
lineListShow: false, // 班车拖拽
message: "",
// 车队原始数组
cat: {
name: "cat",
put: true, //可以拖入
pull: true,
},
// 司机原始数组
driver: {
name: "driver",
put: true, //可以拖入
pull: true,
},
line: {
name: "line",
put: "clone", //可以拖入
pull: "clone",
},
lineGroup: {
name: "line",
put: true, //可以拖入
pull: true,
},
// 表格拖动规则
tripListGroup: {
name: "itxst",
pull: true, //B组拖拽时克隆到A组
put: true,
},
// 二维数据动态切换
groupList: [
{
tripTxet: "班车1",
tripList: [
{
tripListTxet: "01",
id: 2345,
catListTiem: [
{
id: 111,
name: "浙GDU6858",
catNum: "1210Km",
},
],
driverListTiem: [{ id: 51, name: "林炳书" }],
lineListTiem: [
{ id: 52, name: "穹灵路石码头" },
{ id: 53, name: "藏书中学" },
{ id: 54, name: "天池村" },
],
},
{
tripListTxet: "02",
id: 2,
catListTiem: [
{
id: 221,
name: "浙GDQ6983",
catNum: "120Km",
},
],
driverListTiem: [{ id: 65, name: "王非非" }],
lineListTiem: [
{ id: 6, name: "穹灵路石码头" },
{ id: 7, name: "藏书中学" },
{ id: 8, name: "天池村" },
],
},
{
tripListTxet: "03",
id: 3,
catListTiem: [
{
id: 331,
name: "浙GDR1753",
catNum: "120Km"
}
],
driverListTiem: [{ id: 9, name: "林赞利" }],
lineListTiem: [
{ id: 11, name: "穹灵路石码头" },
{ id: 12, name: "藏书中学" },
{ id: 13, name: "天池村" },
],
},
],
},
{
tripTxet: "班车2",
tripList: [
{
tripListTxet: "01",
id: 1452,
catListTiem: [
{
id: 441,
name: "浙GDE3583",
catNum: "120Km",
}
],
driverListTiem: [{ id: 14, name: "张展" }],
lineListTiem: [
{ id: 15, name: "穹灵路石码头" },
{ id: 16, name: "藏书中学" },
{ id: 17, name: "天池村" },
],
},
{
tripListTxet: "02",
id: 5,
catListTiem: [{
id: 551,
name: "浙GDS8088",
catNum: "120Km",
}],
driverListTiem: [{ id: 18, name: "邓超" }],
lineListTiem: [
{ id: 19, name: "穹灵路石码头" },
{ id: 21, name: "藏书中学" },
{ id: 22, name: "天池村" },
],
},
{
tripListTxet: "03",
id: 6,
catListTiem: [
{
id: 661,
name: "浙GDV6609",
catNum: "120Km",
}
],
driverListTiem: [{ id: 23, name: "南争练" }],
lineListTiem: [
{ id: 24, name: "穹灵路石码头" },
{ id: 25, name: "藏书中学" },
{ id: 26, name: "天池村" },
],
},
],
},
],
catList: [
{ id: 1111, name: "浙GDP0638", catNum: "120Km", },
{ id: 11112, name: "浙GDP3917", catNum: "120Km", },
{ id: 11113, name: "浙GDX3823", catNum: "120Km", },
{ id: 11114, name: "浙GDK8228", catNum: "120Km", },
{ id: 11115, name: "浙GDX2166", catNum: "120Km", },
],
driverList: [
{ id: 1, name: "张二辉" },
{ id: 2, name: "方龙" },
{ id: 3, name: "何俊" },
{ id: 4, name: "杨秀品" },
{ id: 5, name: "方俭侠" },
],
lineList: [
{ id: 1, name: "三香公园" },
{ id: 2, name: "三香新村" },
{ id: 3, name: "三香广场" },
{ id: 4, name: "彩香新村" },
{ id: 5, name: "彩虹新村" },
],
moveObj: {
id: undefined,
name: undefined,
catNum: 0,
tripListId: undefined, // 子数据外面id
}, // 移动对象
removeObj: {
id: undefined,
name: undefined,
catNum: 0,
tripListId: undefined, // 子数据外面id
}, // 移出对象
originaNum: 0, // 原数据发生交互
sonNum: 0, //子数据发生交互
};
},
mounted() { },
methods: {
// 原数据开始拖动
originalStart(e, key) {
// 原车牌拖拽 停止其他拖拽
if (key === 1) {
this.lineListShow = true;
this.tripListShow = true;
this.driverListShow = true;
this.moveObj.id = this.catList[e.oldIndex].id; // 获取数据
this.moveObj.name = this.catList[e.oldIndex].name;
this.moveObj.catNum = this.catList[e.oldIndex].catNum;
this.moveObj.tripListId = undefined;
}
// 司机拖拽
if (key === 2) {
this.catListShow = true;
this.lineListShow = true;
this.tripListShow = true;
}
// 路线
if (key === 6) {
this.catListShow = true;
this.tripListShow = true;
this.driverListShow = true;
}
// 表单拖拽
if (key === 3) {
this.catListShow = true;
this.lineListShow = true;
this.driverListShow = true;
}
},
// 原数据发生交互
originalSort(e, key) {
console.log("原数据发生交互", key, this.moveObj.tripListId, this.sonNum);
if (!this.removeObj.tripListId && this.removeObj.id) {
this.catList.push({
id: this.removeObj.id,
name: this.removeObj.name,
catNum: this.moveObj.catNum
});
}
// 子数据与原数据的交互
if (this.moveObj.tripListId && this.sonNum === 0) {
this.groupList.map((i) => {
i.tripList.map((j) => {
console.log(j.catListTiem)
if (j.catListTiem.length === 0) {
j.catListTiem.push({
id: undefined,
name: undefined,
catNum: "0KM",
})
}
});
});
}
},
//数据开始拖拽
start(key, item, index) {
if (key === 4) {
this.lineListShow = true;
this.tripListShow = true;
this.driverListShow = true;
}
// 司机拖拽
if (key === 5) {
this.catListShow = true;
this.lineListShow = true;
this.tripListShow = true;
}
// 路线
if (key === 7) {
this.catListShow = true;
this.tripListShow = true;
this.driverListShow = true;
}
},
/**
* start 开始拖动时触发的事件
add 从一个数组拖拽到另外一个数组时触发的事件
remove 移除事件
update 拖拽变换位置时触发的事件
end 拖拽完成时的事件
choose 鼠标点击选中要拖拽元素时的事件
unchoose 选中后松开鼠标的事件
sort 位置变化时的事件
clone 从一个数组拖拽到另外一个数组时触发的事件和add不同,clone是复制了数组元素
*/
// 被拖动项
originalEnd(key) {
console.log("原数据结束", key);
this.sonNum = 0;
this.end();
},
// 开始拖动 子车牌被拖拽 记录数据moveObj
startSon(key, item, index) {
console.log("开始拖动", key, item, index);
this.moveObj.id = item.catListTiem[0].id;
this.moveObj.name = item.catListTiem[0].name;
this.moveObj.catNum = item.catListTiem[0].catNum;
this.moveObj.tripListId = index;
if (key === 4) {
this.lineListShow = true;
this.tripListShow = true;
this.driverListShow = true;
}
},
// 子数据发生交互
sortSon(key, id, items) {
console.log("子数据发生交互", key, id, items, this.sonNum, this.moveObj);
this.sonNum++;
if (this.sonNum === 2) {
//是子数据之前的交互
this.groupList.map((i) => {
i.tripList.map((j) => {
if (j.catListTiem && j.catListTiem.length > 1) {
j.catListTiem.forEach((item, index, arr) => {
console.log(item);
if (item.id != this.moveObj.id) {
this.removeObj.id = item.id;
this.removeObj.name = item.name;
this.removeObj.catNum = item.catNum;
this.removeObj.tripListId = this.moveObj.tripListId; // 拖拽的外部id
arr.splice(index, 1);
}
});
}
});
});
}
if (this.sonNum === 1 && !this.moveObj.tripListId) {
//原数据与子数据交互
this.groupList.map((i) => {
i.tripList.map((j) => {
if (j.catListTiem && j.catListTiem.length > 1) {
j.catListTiem.forEach((item, index, arr) => {
console.log(item);
if (item.id != this.moveObj.id) {
this.removeObj.id = item.id;
this.removeObj.name = item.name;
this.removeObj.catNum = item.catNum;
this.removeObj.tripListId = undefined; // 拖拽的外部id
arr.splice(index, 1);
}
});
}
});
});
}
},
// 子被拖动项
endSon(key) {
console.log("结束了", key, this.removeObj, this.sonNum);
// this.tripListId 子数据会被存储
//this.tripListId =2 是子数据与子数据之间变换位置
if (this.sonNum === 2 && this.removeObj.tripListId) {
console.log("子数据发生交互");
this.groupList.map((i) => {
i.tripList.map((j) => {
console.log("结束了!", key);
if (j.id === this.removeObj.tripListId) {
j.catListTiem.push({
id: this.removeObj.id,
name: this.removeObj.name,
catNum: this.removeObj.catNum
});
}
});
});
this.sonNum = 0;
} else {
// 重置子数据的次数
this.sonNum = 0;
}
this.end();
},
//被接受项触发
addSon(key, id) {
// console.log("BAIO", key, id);
},
//被接受项触发
add(key, id) {
// console.log("BAIO", key, id);
},
// 重置数据
ert() {
this.moveObj = {
id: undefined,
name: undefined,
catNum: undefined,
tripListId: undefined, // 子数据外面id
}; // 移动对象
this.removeObj = {
id: undefined,
name: undefined,
catNum: undefined,
tripListId: undefined, // 子数据外面id
}; // 移出对象
},
// 被拖动结束,被拖动触发
end(key, item) {
this.catListShow = false;
this.tripListShow = false;
this.driverListShow = false;
this.lineListShow = false;
this.ert();
},
},
};
</script>
<style scoped>
/*定义要拖拽元素的样式*/
.ghostClass {
background-color: blue !important;
}
.chosenClass {
background-color: red !important;
opacity: 1 !important;
}
.dragClass {
background-color: blueviolet !important;
opacity: 1 !important;
box-shadow: none !important;
outline: none !important;
background-image: none !important;
}
.itxst {
-moz-user-select: none;
/*Firefox私有属性*/
-webkit-user-select: none;
/*WebKit内核私有属性*/
-ms-user-select: none;
/*IE私有属性(IE10及以后)*/
-khtml-user-select: none;
/*Khtml内核私有属性*/
-o-user-select: none;
/*Opera私有属性*/
user-select: none;
/*Cs53属性*/
}
.title {
padding: 6px 12px;
background: #2c3e50;
color: blue;
}
.col {
width: 40%;
flex: 1;
padding: 10px;
border: solid 1px #eee;
border-radius: 5px;
float: left;
}
.col+.col {
margin-left: 10px;
}
.item {
padding: 6px 12px;
margin: 0px 10px 0px 10px;
border: solid 1px #eee;
background-color: #f1f1f1;
}
.item:hover {
background-color: #fdfdfd;
cursor: move;
}
.item+.item {
border-top: none;
margin-top: 6px;
}
</style>
第五步 效果