基于vuedraggable.js 嵌套数据开发的拖拽功能

本贴 适用与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>

第五步  效果  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值