使用vuedraggable 对一个 `二维列表` 实现拖拽修改

2023-05-16

使用vuedraggable 对一个 二维列表 实现拖拽修改

vuedraggable实现座位布局拖拽修改

方案一

修改 end,和move,在move中获取移动的元素值,和目的地元素值,在end中交换这两个元素

局限

  • 元素需要是唯一值,不能有重复的
    因为每次只能获取到值,而不是元素的位置,这就导致需要遍历整个列表查询位置,很麻烦
  • 在创建删除队列后,无法将元素拖到删除队列

实现

<vue-draggable
      :disabled="!draggable"
      v-model="arrange[row-1]"
      group="arrange"
      :move="dragMoveHandler"
      @end="dragEndHandler"
  >
  	<!--这里是每行前面的序号-->
    <div class="seat-arrange-col" slot="header" style="user-select: none;">
      <div class="col-index">
        {{ row }}
      </div>
    </div>
    <div class="seat-arrange-col" v-for="col in arrange[row - 1].length" :key="'col' + col">
      <seat-block :key="'row' + row + 'col'+ col" :is-select="selectStatus[row-1][col-1]"
                  :type="arrange[row-1][col-1]"
                  :row="row - 1"
                  :col="col - 1"
                  @seat-select="selectBlockHandler"
                  :isDrag="draggable"
      />
    </div>
    <!--这里是没行后面的添加按键-->
    <div class="seat-arrange-col" slot="footer">
      <div class="col-bt">
        <el-button v-if="draggable" icon="el-icon-plus" type="primary"
                   circle
                   size="mini"
                   :disabled="!canAdd(arrange[row-1])"
                   @click="addSeatHandler(row-1)"
        >
        </el-button>
      </div>
    </div>
</vue-draggable>
dragMoveHandler(evt, originalEvent) {
  this.moveStart = { element: evt.draggedContext.element, index: evt.draggedContext.index }
  this.moveEnd = { element: evt.relatedContext.element, index: evt.relatedContext.index }
  return false
},
dragEndHandler(evt) {
  let relatedRow = -1, draggedRow = -1
  /*start:查询元素*/
  for (let i = 0; i < this.arrange.length; i++) {
    if (draggedRow !== -1 && relatedRow !== -1) break
    if (draggedRow === -1 && this.arrange[i][this.moveStart.index] === this.moveStart.element) {
      draggedRow = i
    }
    if (relatedRow === -1 && this.arrange[i][this.moveEnd.index] === this.moveEnd.element) {
      relatedRow = i
    }
  }
  /*end*/
  /*start:交换对调的元素 更新矩阵*/
  this.$set(this.arrange[draggedRow], this.moveStart.index, this.moveEnd.element)
  this.$set(this.arrange[relatedRow], this.moveEnd.index, this.moveStart.element)
  /*end*/
},

效果(为了导出的gif比较小,就去色了)

演示一

方案二

突然发现 可以在 vue-draggable标签里添加自定义标签,可以从move的tofrom里面的$attrs拿到,这就好办了,以前那种方法就是因为不知道怎么获取移动开始元素和目的地元素的信息,才只能用全局搜索的方法定位,现在的话可以直接获取就好办多了

在这里插入图片描述

实现(代码写得很乱,能用就行,哈哈哈哈)

思路就是在vue-draggable 加属性用来标记属于哪个分组以及是哪一行,我用的divide表示分组,row表示是二维数组的哪一行

vue那里就是覆写move和end,move里面记录每次移动的参数,最后一次的参数就是目的地,end里面就是判断从那里移动到哪里,并执行移动

移动需要用this.$set或者是其他能出发更新的,比如数组的pop,push等方法,这里用的splice(arr,index,remove,...addItem),第一个参数的数组,第二个是操作位置,第三个是在这个位置往后要移除多少元素,后面的参数是移除后插入的元素

<vue-draggable
      :disabled="!draggable"
      v-model="arrange[row-1]"
      group="arrange"
      :row="row-1"
      divide="arrange"
      :move="dragMoveHandler"
      @end="dragEndHandler($event,'arrange')"
  >
    <div class="seat-arrange-col" slot="header" style="user-select: none;">
      <div class="col-index">
        {{ row }}
      </div>
    </div>
    <div class="seat-arrange-col" v-for="col in arrange[row - 1].length" :key="'col' + col">
      <seat-block :key="'row' + row + 'col'+ col" :is-select="selectStatus[row-1][col-1]"
                  :type="arrange[row-1][col-1]"
                  :row="row - 1"
                  :col="col - 1"
                  @seat-select="selectBlockHandler"
                  :isDrag="draggable"
      />
    </div>
    <div class="seat-arrange-col" slot="footer">
      <div class="col-bt">
        <el-button v-if="draggable" icon="el-icon-plus" type="primary"
                   circle
                   size="mini"
                   :disabled="!canAdd(arrange[row-1])"
                   @click="addSeatHandler(row-1)"
        >
        </el-button>
      </div>
    </div>
</vue-draggable>
dragMoveHandler(evt, originalEvent) {
  let from = evt.from.__vue__.$attrs
  let to = evt.to.__vue__.$attrs
  if(from == null || to == null) return;
  this.moveFrom = { row: from.row, index: evt.draggedContext.index, divide: from.divide }
  this.moveTo = { row: to.row, index: evt.relatedContext.index, divide: to.divide }
  return false // 阻止默认的拖拽
},
dragEndHandler(evt) {
   // 非法移动判断
  if (this.moveTo.divide === 'arrange' && this.moveTo.index == null) return

  // 禁止删除列交换拖动
  if (this.moveFrom.divide === this.moveTo.divide === 'deleted') return
  let elementTo = this.getElement(this.moveTo.divide, this.moveTo.row, this.moveTo.index)
  let elementFrom = this.getElement(this.moveFrom.divide, this.moveFrom.row, this.moveFrom.index)
  // 从删除列拖到正常列
  if (this.moveFrom.divide === 'deleted' && this.moveTo.divide === 'arrange') {
    // 只有拖到不为空的列才交换,不然是填充到这一列
    if (elementTo > 0) {
      this.$set(this.arrangeDeleted, this.moveFrom.index, elementTo)
    } else {
      this.arrangeDeleted.splice(this.moveFrom.index, 1)
    }
    this.$set(this.arrange[this.moveTo.row], this.moveTo.index, elementFrom)
  }
  // 正常列拖动都是交换
  if (this.moveFrom.divide === 'arrange' && this.moveTo.divide === 'arrange') {
    this.$set(this.arrange[this.moveFrom.row], this.moveFrom.index, elementTo)
    this.$set(this.arrange[this.moveTo.row], this.moveTo.index, elementFrom)
  }
  // 正常列拖到删除列 正常列填充-1,删除列添加元素
  if (this.moveFrom.divide === 'arrange' && this.moveTo.divide === 'deleted') {
    this.arrangeDeleted.push(elementFrom)
    this.$set(this.arrange[this.moveFrom.row], this.moveFrom.index, -1)
  }
},
getElement(divide, row, index) {
  if (divide === 'deleted') {
    return this.arrangeDeleted[index]
  } else if (divide === 'arrange') {
    return this.arrange[row][index]
  }
  return undefined
},

效果(完美,只需要处理下删除列,让它自动换行)

演示二

缺陷

因为是交换元素,所以在移动到删除列的时候需要有个格子在那才能拖过去

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用vuedraggable 对一个 `二维列表` 实现拖拽修改 的相关文章

  • 十大经典排序算法

    原文地址 xff1a 一文搞掂十大经典排序算法 不才伟才的博客 CSDN博客 一文搞掂十大经典排序算法 今天整理一下十大经典排序算法 1 冒泡排序 越小的元素会经由交换慢慢 浮 到数列的顶端 算法演示 算法步骤 比较相邻的元素 如果第一个比
  • ubuntu 更新阿里源

    原文地址 xff1a https www cnblogs com moyu557 p 10710689 html 查看新版本信息 lsb release c Ubuntu 12 04 LTS 代号为precise Ubuntu 14 04
  • 旋转编码器工作原理

    原文地址 xff1a https blog csdn net weixin 42562514 article details 89435902 一 旋转编码器的原理和特点 xff1a 旋转编码器是集光机电技术于一体的速度位移传感器 当旋转编
  • the read modes of FPGA FIFO —FWFT and Standard

    1 FWFT first word fall through 模式 xff1a 当rd en由低跳变到高电平时候 xff0c FIFO读出的数据FIFO dout 立即读出来 2 Standard 标准模式 xff1a 当rd en由低跳变
  • gdb x 命令详解

    gt examine命令 x xff1a 查看内存地址中的值 格式 xff1a x lt n f u gt lt addr gt n 是正整数 xff0c 表示需要显示的内存单元的个数 xff0c 即从当前地址向后显示n个内存单元的内容 x
  • 什么是奇偶校验

    校验依据 xff1a 判断传输的一组二进制数据中 34 1 34 的个数是奇数还是偶数 奇校验 xff1a 如果以二进制数据中1的个数是奇数为依据 xff0c 则是奇校验 偶校验 xff1a 如果以二进制数据中1的个数是偶数为依据 xff0
  • linux reboot,卡在“restarting system”

    原因 xff1a 产生这个bug的原因比较多 xff0c 百度一般不好找寻答案 xff0c 建议个位去谷歌 待研究 解决办法 xff1a 在谷歌上提交问题 xff0c 运气好有老外回答 本人就走了一次运 待研究 遇到同样问题的小伙伴可以私信
  • linux多线程调用同一个函数解析

    原文地址 xff1a http blog csdn net mq ydn3102 article details 8546722 问题背景 xff1a 在工作中遇到过一个问题 xff0c 就是在两个线程同时调用同一个函数的时候 xff0c
  • mac地址真的是全球是唯一的吗

    问题 xff1a mac地址真的是全球是唯一的吗 答 xff1a 不是 mac地址在百科中的描述如下 xff1a MAC xff08 Media Access Control xff0c 介质访问控制 xff09 地址 xff0c 也叫硬件
  • linux apt-get安装和卸载命令

    apt get update 更新安装列表 apt get upgrade 升级软件 apt get install software name 安装软件 apt get purge remove software name 卸载软件及其配
  • VMware12安装centOS8(vm虚拟机安装centos8教程)

    VMware12安装centOS8 xff08 vm虚拟机安装centos8教程 xff09 前几天Centos8发布了 xff0c 尽管他是8的第一个版本 xff0c 那么今天我们就在VM12上面安装centOS8吧 xff0c 8这个图
  • linux 7z压缩、解压命令

    原文地址 xff1a https blog csdn net jk110333 article details 7829879 支持 7Z ZIP Zip64 CAB RAR ARJ GZIP BZIP2 TAR CPIO RPM ISO
  • bat脚本中怎么注释命令行

    注释内容 按行注释REM 注释时 xff0c sh不执行后面的语句 xff0c 但是会显示 注释内容 按行注释 注意引用bat变量也是 xff0c 容易混淆 xff1a 注释内容 注意注释文本不能与已有标签重名 xff0c 因为 xff1a
  • C语言常见面试问题

    说一下 static 关键字的作用 static用于修改变量或函数的链接属性 xff0c 从外部链接属性变为内部链接属性 xff0c 变量或函数只能在当前文件访问 对于代码块内部的变量声明 xff0c static用于改变变量的存储属性 x
  • 关于CPU的12个硬核干货!

    作为一名程序员 xff0c 与计算机打交道的日子不计其数 xff0c 不管你玩硬件还是做软件 xff0c 你的世界自然都少不了计算机最核心的 CPU 01 CPU是什么 xff1f CPU与计算机的关系就相当于大脑和人的关系 xff0c 它
  • C语言typedef关键字及其使用

    在C语言中有一个typedef关键字 xff0c 其用来定义用户自定义类型 当然 xff0c 并不是真的创造了一种数据类型 xff0c 而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名 总之 xff0c 可以使用ty
  • 内存中堆的基本概念

    一 什么是堆 xff1f C语言堆是由malloc calloc realloc 等函数动态获取内存的一种机制 使用完成后 xff0c 由程序员调用free 等函数进行释放 使用时 xff0c 需要包含stdlib h头文件 C 43 43
  • C#可以做什么

    C xff08 C Sharp xff09 是Microsoft的新编程语言 xff0c 被誉为 C C 43 43 家族中第一种面向组件的语言 然而 xff0c 许多人认为C 更像是Java的一种克隆 xff0c 或者是Microsoft
  • 计算机术语中的"透明"

    计算机中术语透明性是什么意思 xff1f 一 透明性 xff08 transparency xff09 定义 xff1a 在通信网中 xff0c 不改变信号形式和信息内容的端到端传输 二 透明性现象 xff1a 在计算机技术中 xff0c
  • 编辑器、编译器与集成开发环境(IDE)的区别

    一 编辑器 编辑器的概念很简单 xff0c 百度百科上这么写道 xff1a 编辑器是软件程序 xff0c 一般是指用来修改电脑档案的编写软件 xff0c 但也有人称 PE2 HE4 xff08 汉书 xff09 等文书软件为编辑器 常见的编

随机推荐