vue.draggable拖拽,项目中三个表格互相拖拽的实例操作,前端分页等更多小技巧~

news2025/1/16 1:39:49

vue.draggable中文文档 - itxst.com官网在这里,感兴趣的小伙伴可以看看。

NPM或yarn安装方式

yarn add vuedraggable
npm i -S vuedraggable

UMD浏览器直接引用JS方式

<script src="https://www.itxst.com/package/vue/vue.min.js"></script>
<script src="https://www.itxst.com/package/sortable/Sortable.min.js"></script>
<script src="https://www.itxst.com/package/vuedraggable/vuedraggable.umd.min.js"></script>

导入组件

import draggable from 'vuedraggable'

//注册draggable组件

components: { draggable, }

首先记录一下我的项目功能需求,是三个表格可以互相拖动,我主要还是看的多列拖动的案列。vue.draggable两列或多列之间相互拖动 - itxst.com

多列组件拖动设置相同的group名就可以相互拖拽了这是大家需要知道的一点

其次就是group包含是什么,取一个name,在pull,put里面就标记可以拖出/入/拷贝

 tableA: {

        name: "itxst",

        pull: true, //可以拖出

        put: true //可以拖入

      },

最后就是拖动的数据结构要一致,什么意思呢?通俗来说是在一个表里面姓名这个字段用的是name,另外一张表的姓名字段用的是xm,那么这条数据的拖动就是有问题的~感兴趣的朋友可以自行试验。以下是我的代码,有拖拽和前端表格分页的联合使用,会稍微复杂一些些。

表一的vue如下所示:这里由于工作的关系,不能把label里面的完整值展示出来。这里的表结构的稍稍有些复杂,他是在数组里面有若干对象,每个 对象有一个数组及若干对象,数组里面又有若干对象。

<el-table :data="tableData" class="my-new-table" border height="390" :span-method="spanMethod">
                    <el-table-column prop="depName" label="单" width="100" />
                    <el-table-column prop="zwmc" label="岗" width="120" />
                    <el-table-column prop="zwjb" label="职" width="80" />

                    <el-table-column prop="name" label="编" width="95" />
                    <!-- <el-table-column prop="name" label="变" width="150" /> -->
                    <el-table-column label="变" width="320">
                      <el-table-column prop="province" label="本" width="80">
                      </el-table-column>
                      <el-table-column prop="city" label="平" width="80">
                      </el-table-column>
                      <el-table-column prop="address" label="女" width="80">
                      </el-table-column>
                      <el-table-column prop="zip" label="年" width="80">
                      </el-table-column>
                    </el-table-column>

                    <el-table-column label="配" :width="elTableColumnWidth > 890 ? elTableColumnWidth : 890">
                      <template slot-scope="scope">


                        <draggable :group="tableA" v-model="scope.row.SimuCadres" @end="saveListsTableData"
                          @start="start1" @add="add1" :class="{ warrperPeople: true, [scope.$index]: true }">
                          <div class="people" v-for="citem in scope.row.SimuCadres" v-if="citem.xm" :key="citem.cid">
                            <div>
                              <img src="../../../static/images/rmMn3/gantanhao.png" alt="">
                              <img v-if="citem.zzmm === '中共党员' && citem.zzmm === '预备党员'"
                                src="../../../static/images/rmMn3/fei.png" alt="">
                              <img v-if="citem.xb === '女'" src="../../../static/images/rmMn3/nv.png" alt="">

                            </div>

                            <span>{{ citem.xm ? citem.xm : "无名" }}</span>
                          </div>
                        </draggable>


                      </template>
                    </el-table-column>

                  </el-table>
                  <div class="pagination-box-c" style="display:flex;justify-content:space-between;margin-top:16px">
                    <el-pagination background layout="prev, pager, next" :total="currentListDataT.total ? currentListDataT.total : 1
                      " :current-page.sync="currentListDataT.index" :page-size="pageSizePagination"
                      :page-sizes="[5, 10]" @prev-click="changeListSizeT" @next-click="changeListSizeT"
                      @current-change="changeListSizeT"></el-pagination>
                  </div>
   

 这里我用draggable包裹起来的东西,就是属于要拖动的范畴。:group="tableA"指的是组,v-model="scope.row.SimuCadres"绑定的数据,@end="saveListsTableData"@start="start1" @add="add1"

 表二和表三的vue如下所示:这里由于工作的关系,不能把label里面的完整值展示出来。这里的表结构简单,数组里面有若干对象。

    <div class="table-container tableTwo">
                      <div class="table-header">
                        <div class="table-cell">姓名</div>
                        <div class="table-cell">出生年月</div>
                        <div class="table-cell">现</div>
                        <div class="table-cell noright">操作</div>
                      </div>
                      <draggable class="table-row table2" :group="tableB" v-model="tableOut" @end="saveListsTableDataTwo"
                        @start="starTwo" @add="addTwo">
                        <div style="display: flex" v-for="(item, index) in tableOut" :key="Math.random() + index + 'asd'">
                          <span class="table-cell">{{ item.xm }}</span>
                          <span class="table-cell">{{ item.csny }}</span>
                          <span class="table-cell">{{ item.xrz }}</span>
                          <span class="table-cell" style="border-right: none">
                            <el-button class="scope-three-button" size="mini" type="text"
                              @click="opCompare(item.CadreID)">
                              {{
                                compareList.includes(item.CadreID)
                                ? "取消对比"
                                : "对比"
                              }}
                            </el-button>
                          </span>
                        </div>
                      </draggable>
                    </div>

draggable包裹起来的东西,就是属于要拖动的范畴:group="tableB" v-model="tableOut" @end="saveListsTableDataTwo"  @start="starTwo" @add="addTwo"

 

 讲完了vue代码,接下来分享一下为什么要写分页,前端分页的逻辑是什么,与后端写分页有什么区别:

这里阿尭写分页是因为,前端自己拖动的数据,没有点击保存,如果拖动一次调一次后端的接口,非常没有必要,大量的网络请求浪费资源。所以用户在拖数据后再保存完数据,我们拖动的时候,数据一页非常多,看起来不美观,而后端又不知道我们有多少数据,所以这里需要前端写一个分页,逻辑如下:

 

//@end   
 saveListsTableData(e, e1, e2) {
      console.log(e);
      // 获取表格拖拽出去以后的数据!!!
      this.tableData.forEach(obj => {
        obj.SimuCadres.forEach(item => {
          const xm = item.xm;
          // 在这里可以使用 cname 进行后续操作
          console.log(xm);
        });
      });
    },
  start1(e) {
      // 获取表格开始拖拽的数据!!!
    },

 

  add1(e) {
      // 拖入了数据对应行
      const index = e.to._prevClass.split(" ")[0];
      console.log("表格一", index);
      const draggedItem = this.tableData[index];
      const allDraggedItem = this.allTableData[index];
      // 判断拖拽的对象ID与数组中的ID是否有冲突,此时需要注意的时候,
      // 拖拽的时候tableData和allTableData内部已经push了这条数据,所以要去找当前的数组里面的对象的id是否有两个完全一样的,
      // 并且再与e.item._underlying_vm_.CadreID相同,则把这条数据从tableData里面去重
      // 先检查是否有两个完全相同的 CadreID
      const duplicateCadre = draggedItem.SimuCadres.find((c1, index1) => {
        return draggedItem.SimuCadres.some((c2, index2) => {
          return c1.CadreID === c2.CadreID && index1 !== index2;
        });
      });
      if (
        duplicateCadre &&
        duplicateCadre.CadreID === e.item._underlying_vm_.CadreID
      ) {
        // 存在两个完全相同的 CadreID 并且与 e.item._underlying_vm_.CadreID 相同
        this.$message({
          showClose: true,
          message: "该岗位已经存在该干部了",
          type: "warning"
        });
         // 若是存在相同的ID,此时应该获取的e.item,拿到拖拽的数据,再push进来源表的数组中的原位置
        if (e.from._prevClass == "table-row table3") {
          let index = parseInt(e.oldIndex);
          this.inCadreListTotal.splice(index, 0, e.item._underlying_vm_);
          this.inCadreListTotal = this.inCadreListTotal.filter(
            (c, index, self) => {
              return !self
                .slice(index + 1)
                .some(item => item.CadreID === c.CadreID);
            }
          );
          this.table3Index = 2;
        }
        if (e.from._prevClass == "table-row table2") {
          let index = parseInt(e.oldIndex);
          this.saveTableOut.splice(index, 0, e.item._underlying_vm_);
          this.saveTableOut = this.saveTableOut.filter(
            (c, index, self) => {
              return !self
                .slice(index + 1)
                .some(item => item.CadreID === c.CadreID);
            }
          );
          this.table2Index = 2;
        }


        // 从 tableData 中去重
        draggedItem.SimuCadres = draggedItem.SimuCadres.filter(
          (c, index, self) => {
            return !self
              .slice(index + 1)
              .some(item => item.CadreID === c.CadreID);
          }
        );
        // 从 allTableData 中去重
        allDraggedItem.SimuCadres = draggedItem.SimuCadres.filter(
          (c, index, self) => {
            return !self
              .slice(index + 1)
              .some(item => item.CadreID === c.CadreID);
          }
        );
      } else {
        this.table3Index = 1;
      }
    },
    // 表格2
    saveListsTableDataTwo(e) {
      
      if (this.table2Index == 2) {
        this.table2Index = 1;
        this.currentListDataZ.total = this.saveTableOut.length;
      if (this.tableOut.length == 0) {
        this.currentListDataZ.index =
          this.currentListDataZ.index > 1
            ? this.currentListDataZ.index - 1
            : this.currentListDataZ.index;
      }
      let startIndex = (this.currentListDataZ.index - 1) * 5;
      let endIndex = this.currentListDataZ.index * 5;
      this.tableOut = this.saveTableOut.slice(startIndex, endIndex);

        return;
      }
      if (e.from._prevClass == e.to._prevClass) {
        return;
      }
      this.saveTableOut = this.saveTableOut.filter(
        item => item.CadreID !== e.item._underlying_vm_.CadreID
      );
      this.currentListDataZ.total = this.saveTableOut.length;
      if (this.tableOut.length == 0) {
        this.currentListDataZ.index =
          this.currentListDataZ.index > 1
            ? this.currentListDataZ.index - 1
            : this.currentListDataZ.index;
      }
      let startIndex = (this.currentListDataZ.index - 1) * 5;
      let endIndex = this.currentListDataZ.index * 5;
      this.tableOut = this.saveTableOut.slice(startIndex, endIndex);
    },
    starTwo(e) {
      // 拖走了谁,只能获取拖走的元素,不能获取拖完后的表格数据,需要在@end里面查看
      console.log(e);
      console.log("this.tableOut111", this.tableOut);
    },
    addTwo(e) {
      // 拖入了谁
      console.log("表格2", e.item._underlying_vm_);
      this.tableOut = this.tableOut.filter(
        (item, index, self) =>
          index === self.findIndex(obj => obj.CadreID === item.CadreID)
      );
      this.saveTableOut.some(
        item => item.CadreID === e.item._underlying_vm_.CadreID
      ) || this.saveTableOut.push(e.item._underlying_vm_);

      this.currentListDataZ.total = this.saveTableOut.length;
      const pageSize = 5; // 每页显示的条数
      const currentPage = this.currentListDataZ.index; // 当前页码
      const maxPageIndex = Math.ceil(this.saveTableOut.length / pageSize); // 最大页码
      console.log(maxPageIndex);
      if (currentPage < maxPageIndex) {
        this.currentListDataZ.index = maxPageIndex;
      }
      let startIndex = (this.currentListDataZ.index - 1) * 5;
      let endIndex = this.currentListDataZ.index * 5;
      this.tableOut = this.saveTableOut.slice(startIndex, endIndex);

      console.log(" this.saveTableOut", this.saveTableOut);
    },

 在之前我介绍过表一结构的稍稍有些复杂,他是在数组里面有若干对象,每个 对象有一个数组及若干对象,数组里面又有若干对象。我们要做的是把数据拖入这个数组的对象的数组的对象中,听起来有些绕,看图:

 类型一个表中若干条这个的数据,我们取其中一个单元格来放拖入的数据,首先你要拿到你拖入的数据在哪一行对吧,因为要对拖入的数据做一个去重,拖入重复的没有意义。怎么去获得拖入的行号?在draggable绑定一个动态 :class="{ warrperPeople: true, [scope.$index]: true },这里将表格的index传入,在拖拽事件中,通过e的属性可以看到index ,从而拿到行号。好了拖拽事件就介绍到这里,欢迎各位留言讨论~

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1047595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是超声波清洗机?工作原理是什么?2023年超声波清洗机推荐

超声波清洗机的优点可真是太多了&#xff01;&#xff01;&#xff01;比如超声波清洗的效果很不错&#xff0c;清洁度也很高&#xff0c;清洗速度快&#xff0c;不需要用手去接触清洗液&#xff0c;对于深孔&#xff0c;细缝&#xff0c;工件暗区也能清洗干净&#xff0c;清洗…

企业怎样选择适合的服务器租用?

随着互联网技术的发展&#xff0c;如何选择企业需要的服务器租用来满足需求是很多企业目前在考虑的问题&#xff0c;今天就让小编来给大家讲一讲吧&#xff01; 确定好服务器的规模和用途。企业首先根据自身的业务情况选择服务器的数量和规模还有性能&#xff0c;小型企业可以…

Echarts 自适应不生效解决(CPK分析工具直方图为例)

示例代码为左上方的CPK分析直方图组件 <template><div ref="cpk" id="cpk" style="height: 300px; width: 100%"></div> </template><script> import * as echarts from "echarts"; import { deboun…

【多线程初阶】多线程案例之定时器

文章目录 前言1. 什么是定时器2. 标准库中的定时器3. 自己实现一个定时器总结 前言 本文主要给大家讲解多线程的一个重要案例 — 定时器. 关注收藏, 开始学习吧&#x1f9d0; 1. 什么是定时器 定时器也是软件开发中的一个重要组件 类似于一个 “闹钟”. 达到一个设定的时间之…

Figma中文插件,让设计工作事半功倍的6大神器

Figma 凭借强大的设计功能和出色的协同体验&#xff0c;成为当前最受欢迎的 UI 设计工具之一。其插件生态为设计师提供了更多实用功能和可能性&#xff0c;大幅提高工作效率。即时设计在原型、交互、设计、协作等方面与 Figma 旗鼓相当&#xff0c;但更考虑本土设计师的实际需求…

数字孪生与GIS:优化公共交通的未来

数字孪生结合地理信息系统&#xff08;GIS&#xff09;在公共交通领域具有潜在的重大贡献&#xff0c;这种结合可以帮助城市更高效地规划、运营和改进公共交通系统。以下是一些关键方面的讨论&#xff0c;以说明数字孪生和GIS在这一领域的作用&#xff1a; 数字孪生技术的兴起…

【计算机网络】 基于TCP的简单通讯(服务端)

文章目录 流程伪代码代码实现加载库创建套接字绑定ip地址和端口号监听接受连接收发数据关闭套接字、卸载库 流程伪代码 //1、加载库——WSAStartup()//2、创建套接字——socket()//3、绑定ip和端口号——bind()//4、监听——listen()while(true){//5、接受连接——accept()whi…

kkplayer用户手册

本软件不使用任何敏感权限都可拒绝。所有资源均来自互联网&#xff0c;本软件仅供学习参考使用。 有任何问题可先尝试重装最新版 1.青少年模式 2.搜索方法 3.单个添加视频源 4.批量添加视频源 5.无法播放,无法全屏 6.DLNA投屏 7.隐私权限问题 8.数据备份和分享 9.关于广告 1. …

线程池解析

文章目录 1、平时使用哪些线程池&#xff0c;线程池默认的参数有哪些2、线程池的7个参数3、线程池状态①、线程池各个状态切换图&#xff1a; 4、线程池的使用5、线程池的好处6、线程池的整个流程7、Java的线程池说说①、线程池概念②、线程池的创建③、任务执行④、四种拒绝策…

005:根据股票代码和起始日期获取K线数据

我们改进《001》中的部分&#xff0c;因为他他没法在可视化界面输入信息&#xff0c;这样太麻烦。我们设法在可视化界面输入股票代码和起始日期&#xff0c;这样可以灵活得多。这部分&#xff0c;我们仍旧只获取日K线的数据。 import tkinter as tk from tkinter import messa…

Final Draft 12.0.9(简单好用的剧本写作工具)

Final Draft 12是一款专为编剧打造的强大写作工具&#xff0c;它将您的创意转化为精彩剧本的过程变得简单而高效。以下是推荐Final Draft 12的一些理由&#xff1a; 界面设计&#xff1a;Final Draft 12采用了简洁直观的界面设计&#xff0c;使得用户可以专注于创作&#xff0…

C语言的学习快速入门

可以按照以下步骤进行&#xff1a; 了解基本概念和语法&#xff1a;C语言是一种结构化的编程语言&#xff0c;了解基本的语法规则对于入门非常重要。可以学习关键字、变量、数据类型、运算符、控制结构等基本概念。学习编程环境&#xff1a;选择合适的编程环境&#xff0c;例如…

在linux下预览markdown的方法,转换成html和pdf

背景 markdown是一种便于编写和版本控制的格式&#xff0c;但却不便于预览——特别是包含表格等复杂内容时&#xff0c;单纯的语法高亮是远远不够的——这样就不能边预览边调整内容&#xff0c;需要找到一种预览方法。 思路 linux下有个工具&#xff0c;叫pandoc&#xff0c…

关闭手机广告的步骤

关闭手机广告的步骤 小米 1.设置→小米账号→声明与条款→系统广告→系统工具广告→关闭 2.设置→应用设置→应用管理→右上角三个点→设置→关闭“应用升级提醒”&“资源推荐” 3.桌面左滑打开负一屏→划到底部→设置→服务管理→选择关闭项目 4.桌面→打开任意文件夹…

数据库索引的分类

说到BTree首先要说一下B-Tree B-Tree(Balance Tree 多路平衡查找树)是一种平衡的多路搜索树数据结构&#xff0c;用于实现高效的查找、插入和删除操作。B树的特点是每个节点可以存储多个关键字&#xff0c;并且节点的孩子数目与关键字数目相同。通过控制节点的关键字数目和孩子…

最新影视视频微信小程序源码-带支付和采集功能/微信小程序影视源码PHP(更新)

源码简介&#xff1a; 这个影视视频微信小程序源码&#xff0c;新更新的&#xff0c;它还带支付和采集功能&#xff0c;作为微信小程序影视源码&#xff0c;它可以为用户 提供丰富的影视资源&#xff0c;包括电影、电视剧、综艺节目等。 这个小程序影视源码&#xff0c;还带有…

ue5读取自定义文件夹中内容

一、复制文件夹到Content内 二、读取文件内容&#xff0c;直接使用相对路径就可以了/Content&#xff0c;Resource Bundle存储文件夹名的变量。Load Text为自定义的读取json文件的方法&#xff0c;我之前的文章讲了怎么操作。 ue5读取外部文件_艺菲的博客-CSDN博客 三、根据js…

优优嗨聚集团:多地迎来旅游旺季,外卖市场有何变化

随着气温的升高&#xff0c;多地迎来了旅游旺季。据相关数据显示&#xff0c;今年暑期旅游市场异常火爆&#xff0c;全国旅游业收入同比增长了20%。在这样的大背景下&#xff0c;外卖市场也悄然发生了变化。 首先&#xff0c;让我们来看一下旅游市场的现状。据统计&#xff0c;…

Nginx 默认location index设置网站的默认首页

/斜杠代表location定位的路径&#xff0c;路径当中最重要的字段就是root。 root默认值就是html&#xff0c;这个就是nginx安装路径下面的html文件夹作为root的路径。默认不配置就是root下面的内容&#xff0c;index指定了主页的内容。 [rootjenkins html]# echo test > te…

Zotero同步论文、笔记

之前用 Mendeley[1]看论文&#xff0c;看中几个功能&#xff1a; tags&#xff0c;多标签分类&#xff0c;类似微信分组&#xff0c;用来快速筛&#xff08;已添加的&#xff09;某一类文献&#xff1b;同步&#xff0c;包括 pdf 和笔记&#xff08;高亮、便签、tags&#xff…