使用vue-grid-layout完成桌面拖拽布局功能(实现两个元素互换位置)

最近有个项目需要实现和windows桌面类似的图标拖拽功能,找了很多组件都没找到一个合适的,但通过本博主的不懈努力最后发现了两款不错的插件:

  1. sortablejs
  2. vue-grid-layout
    本来一开始我使用的是第一个,但是可能是有点转不过来,最终放弃了第一个插件,但是第二个也确实香,虽然也有不少bug但是也不是不能解决的,下面就回到正题上来给大家粗略说一下:

先上代码吧,怕大家等不及往下拉:

<template>
  <div>
    <grid-layout :layout.sync="layout"
      :col-num="8"
      :row-height="100"
      :is-draggable="true"
      :is-resizable="false"
      :vertical-compact="false"
      :margin="[20, 24]"
      :use-css-transforms="true">
      <grid-item v-for="(item,index) in layout"
        :key="index"
        :item="watchitem(item)"
        :static="item.static"
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        @move="moveEvent"
        @moved="movedEvent" >
        <span class="text">{{item.i}}</span>
      </grid-item>
    </grid-layout>
  </div>
</template>

<script>
var historyLayout = [
  {"x":0,"y":0,"w":1,"h":1,"i":"0", static: false},
  {"x":1,"y":0,"w":1,"h":1,"i":"1", static: false},
  {"x":2,"y":0,"w":1,"h":1,"i":"2", static: false},
  {"x":3,"y":0,"w":1,"h":1,"i":"3", static: false},
  {"x":4,"y":0,"w":1,"h":1,"i":"4", static: false},
  {"x":5,"y":0,"w":1,"h":1,"i":"5", static: false},
  {"x":6,"y":0,"w":1,"h":1,"i":"6", static: false},
  {"x":7,"y":0,"w":1,"h":1,"i":"7", static: false},
  {"x":0,"y":1,"w":1,"h":1,"i":"8", static: false},
  {"x":1,"y":1,"w":1,"h":1,"i":"9", static: false},
  {"x":2,"y":1,"w":1,"h":1,"i":"10", static: false},
  {"x":3,"y":1,"w":1,"h":1,"i":"11", static: false},
  {"x":4,"y":1,"w":1,"h":1,"i":"12", static: false},
  {"x":5,"y":1,"w":1,"h":1,"i":"13", static: false},
  {"x":6,"y":1,"w":1,"h":1,"i":"14", static: false},
  {"x":7,"y":1,"w":1,"h":1,"i":"15", static: false},
  {"x":0,"y":2,"w":1,"h":1,"i":"16", static: false},
  {"x":1,"y":2,"w":1,"h":1,"i":"17", static: false},
  {"x":2,"y":2,"w":1,"h":1,"i":"18", static: false},
  {"x":3,"y":2,"w":1,"h":1,"i":"19", static: false}
];

import { GridLayout, GridItem } from "vue-grid-layout"
export default {
  components: {
      GridLayout,
      GridItem
  },
  data() {
    return {
      layout: [
        {"x":0,"y":0,"w":1,"h":1,"i":"0", static: false},
        {"x":1,"y":0,"w":1,"h":1,"i":"1", static: false},
        {"x":2,"y":0,"w":1,"h":1,"i":"2", static: false},
        {"x":3,"y":0,"w":1,"h":1,"i":"3", static: false},
        {"x":4,"y":0,"w":1,"h":1,"i":"4", static: false},
        {"x":5,"y":0,"w":1,"h":1,"i":"5", static: false},
        {"x":6,"y":0,"w":1,"h":1,"i":"6", static: false},
        {"x":7,"y":0,"w":1,"h":1,"i":"7", static: false},
        {"x":0,"y":1,"w":1,"h":1,"i":"8", static: false},
        {"x":1,"y":1,"w":1,"h":1,"i":"9", static: false},
        {"x":2,"y":1,"w":1,"h":1,"i":"10", static: false},
        {"x":3,"y":1,"w":1,"h":1,"i":"11", static: false},
        {"x":4,"y":1,"w":1,"h":1,"i":"12", static: false},
        {"x":5,"y":1,"w":1,"h":1,"i":"13", static: false},
        {"x":6,"y":1,"w":1,"h":1,"i":"14", static: false},
        {"x":7,"y":1,"w":1,"h":1,"i":"15", static: false},
        {"x":0,"y":2,"w":1,"h":1,"i":"16", static: false},
        {"x":1,"y":2,"w":1,"h":1,"i":"17", static: false},
        {"x":2,"y":2,"w":1,"h":1,"i":"18", static: false},
        {"x":3,"y":2,"w":1,"h":1,"i":"19", static: false}
      ],
      draggable: true,
      resizable: true,
      index: 0,
      newX:0,
      newY:0,
      curBox:'',
    }
  },
  methods: {
    watchitem (item) {
      if(this.curBox != item.i) {
        for (let j = 0; historyLayout[j] != undefined; j++) {
          if(historyLayout[j].i == item.i) {
            item.x = historyLayout[j].x
            item.y = historyLayout[j].y
          }
        }
      }
      return item
    },
    moveEvent (i){
      this.curBox = i
    },
    movedEvent (i, newX, newY) {
      for (let j = 0; historyLayout[j] != undefined; j++) {
        if(historyLayout[j].i == i) {
          this.newX = historyLayout[j].x
          this.newY = historyLayout[j].y
          historyLayout[j].x = newX
          historyLayout[j].y = newY
        }
      }
      for (let j = 0; historyLayout[j] != undefined; j++) {
        if(i!=historyLayout[j].i && historyLayout[j].x === newX && historyLayout[j].y === newY) {
          historyLayout[j].x = this.newX
          historyLayout[j].y = this.newY
        }
      }
    }
  }
}
</script>

<style scoped>
.vue-grid-layout {
    background: #eee;
}
.vue-grid-item:not(.vue-grid-placeholder) {
    background: #ccc;
    border: 1px solid black;
}
.vue-grid-item .resizing {
    opacity: 0.9;
}
.vue-grid-item .static {
    background: #cce;
}
.vue-grid-item .text {
    font-size: 24px;
    text-align: center;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    height: 100%;
    width: 100%;
}
.vue-grid-item .no-drag {
    height: 100%;
    width: 100%;
}
.vue-grid-item .minMax {
    font-size: 12px;
}
.vue-grid-item .add {
    cursor: pointer;
}
</style>

效果(本人是最看不惯别人的文章不带效果的,狗头保护…)

在这里插入图片描述
下面进入正文:

  1. 安装:
npm install vue-grid-layout --save
  1. 导入 && 引用
 import VueGridLayout from 'vue-grid-layout';

 export default {
       components: {
           GridLayout: VueGridLayout.GridLayout,
           GridItem: VueGridLayout.GridItem
       },
   // ... data, methods, mounted (), etc.
 }
  1. 属性 && 方法
    这里就不做过多的讲解,毕竟文档比我写要好
    属性

  2. 这里才最主要是新增代码
    vue-grid-layout中的标识栅格元素是否可拖拽该属性只能将元素向下排,并不能形成左右替换的形式,并且在该组件中也没有元素互相替换位置这种属性,所以我给它加了判定

...
methods: {
    watchitem (item) {
     // 判断当前移动的对象是否导致其他元素发生位移变换
      if(this.curBox != item.i) {
        for (let j = 0; historyLayout[j] != undefined; j++) {
          if(historyLayout[j].i == item.i) {
            item.x = historyLayout[j].x
            item.y = historyLayout[j].y
          }
        }
      }
      return item
    },
    moveEvent (i){
     // 移动时记录当前移动的元素对象
      this.curBox = i
    },
    movedEvent (i, newX, newY) {
      // 将元素最新生成的位置记录在historyLayout中,用来形成判断
      for (let j = 0; historyLayout[j] != undefined; j++) {
        if(historyLayout[j].i == i) {
          this.newX = historyLayout[j].x
          this.newY = historyLayout[j].y
          historyLayout[j].x = newX
          historyLayout[j].y = newY
        }
      }
      // 当元素移动到原本有元素的位置上时,原本位置上的元素迁移到移动前元素的位置上形成互换位置
      for (let j = 0; historyLayout[j] != undefined; j++) {
        if(i!=historyLayout[j].i && historyLayout[j].x === newX && historyLayout[j].y === newY) {
          historyLayout[j].x = this.newX
          historyLayout[j].y = this.newY
        }
      }
    }
  }

以上就是我目前功能的实现,但由于项目时间关系,还没有完善代码,没有写一个将元素插入其中的方法,希望各位有了更好的意见时可以一起分享分享

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值