ElementUI实现el-table列的显示与隐藏和列拖拽(RuoYi分离版)

2023-11-13

显示隐藏步骤思路:

一、table要实现v-for循环添加列的操作

二、给列添加v-if属性 方法返回当前列是否显示隐藏

①在RightToolBar添加列显示隐藏的图标控件                                                                                    

<template>
  <div class="top-right-btn">
    <el-row>
      <el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
        <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="刷新" placement="top">
        <el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
      </el-tooltip>

      <el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns!=undefined">
        <el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px">
          <el-button size="mini" circle icon="el-icon-menu"/>
          <el-dropdown-menu slot="dropdown">
            <template v-for="item in columns">
              <el-dropdown-item><el-checkbox :checked="item.isShow" @change="monitorChange($event,item.label)" :label="item.label"></el-checkbox></el-dropdown-item>
            </template>
          </el-dropdown-menu>
        </el-dropdown>
      </el-tooltip>

    </el-row>
    <el-dialog :title="title" :visible.sync="open" append-to-body>
      <el-transfer
        :titles="['显示', '隐藏']"
        v-model="value"
        :data="columns"
        @change="dataChange"
      ></el-transfer>
    </el-dialog>
  </div>
</template>
<script>
export default {
  name: "RightToolbar",
  data() {
    return {
      // 显隐数据
      value: [],
      // 弹出层标题
      title: "显示/隐藏",
      // 是否显示弹出层
      open: false,
    };
  },
  props: {
    showSearch: {
      type: Boolean,
      default: true,
    },
    columns: {
      type: Array,
    },
  },
  created() {
  },
  methods: {
    // 搜索
    toggleSearch() {
      this.$emit("update:showSearch", !this.showSearch);
    },
    // 刷新
    refresh() {
      this.$emit("queryTable");
    },
    // 右侧列表元素变化
    dataChange(data) {
      for (var item in this.columns) {
        const key = this.columns[item].key;
        this.columns[item].visible = !data.includes(key);
      }
    },
    monitorChange(event,label){
      this.columns.filter(item=>item.label==label)[0].isShow=event
    }
  },
};
</script>
<style lang="scss" scoped>
::v-deep .el-transfer__button {
  border-radius: 50%;
  padding: 12px;
  display: block;
  margin-left: 0px;
}
::v-deep .el-transfer__button:first-child {
  margin-bottom: 10px;
}
</style>

 下列菜单用的是checkBox组 成品效果就是这样的

                                ​​​​​​​        ​​​​​​​        ​​​​​​​        

具体两个父子控件怎么传递数据,这里不过多讲解。

下面是表格的主要代码

<right-toolbar
        :showSearch.sync="showSearch"
        :columns="allTableLabel"
        @queryTable="getList"
      ></right-toolbar>
    </el-row>

    <el-table
      v-loading="loading"
      :data="purchaseList"
      row-key="id"
      border
      ref="purchaseTable"
      @selection-change="handleSelectionChange"
    >


      <template
        v-for="column in tableColumns">
        <el-table-column
          v-if="judgeIsShow(column.label)"
          :key="column.id"
          :prop="column.prop"
          :class-name="column.isDrag"
          :label="column.label"
          :align="column.align"
          :type="column.type"
          :width="column.width"
        >
                  <template v-if="column.scope=='scope'" scope="scope">
                    <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
                  </template>
                  <template v-else-if="column.scope=='slot-scope'" slot-scope="scope">
                    {{scope.row.contractNum}}/{{getUnit(scope.row.quantityUnit)}}
                  </template>
                  <template v-else-if="column.scope=='ClientTag'" slot-scope="scope">
                    <ClientTag :value="scope.row.contractId" :flag="flag" :view="table"/>
                  </template>


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

下边的定义的数据和方法的代码

//elementui测试
      tableColumns:[
        {id:"0",type:"selection",width:"55",align:"center"},
        {id:"1",type:"index",label:"序号",align:"center",scope:"scope"},
        {id:"2",label:"采购合同号",prop:"contractNo",align:"center",isDrag:"drag"},
        {id:"3",label:"原产国",prop:"countryName",align:"center",isDrag:"drag"},
        {id:"4",label:"产品",prop:"productName",align:"center",isDrag:"drag",scope:"ClientTag"},
        {id:"5",label:"合同总数量",prop:"contractNum,quantityUnit",isDrag:"drag",align:"center",scope: "slot-scope"},
        {id:"6",label:"合同总金额",prop:"contractPrice",align:"center"},
      ],

 //elementui的table所有的表头数据
      allTableLabel:[],


//把列的显示和隐藏 存Cookie
setTableShowToCookie(){
      let label="";
      let isShow="";

      let labelArr=[];
      let isShowArr=[];

      this.allTableLabel.forEach((item)=>{
        labelArr.push(item.label)
        isShowArr.push(item.isShow);
      })
      label=labelArr.join(',')
      isShow=isShowArr.join(',')
      Cookies.set("purchaseTableLabel",label)
      Cookies.set("purchaseTableIsShow",isShow)
    },
    getTableShowOfCookie(){
      let label=Cookies.get("purchaseTableLabel");
      let isShow=Cookies.get("purchaseTableIsShow");
      console.log(label)
      if (label==undefined){
        this.allTableLabel=[
          {label:"序号",isShow:true},
          {label:"采购合同号",isShow:true},
          {label:"原产国",isShow:true},
          {label:"产品",isShow:true},
          {label:"合同总数量",isShow:true},
          {label:"合同总金额",isShow:true},
        ];
      }else{
        let labelArr=label.split(",");
        let isShowArr=isShow.split(",");
        let len=labelArr.length;
        console.log("长度为"+len)
        for (let i=0;i<len;i++){
          this.allTableLabel.push({label:labelArr[i],isShow:isShowArr[i]=="true"?true:false});
        }
      }
    },


//判断是否显示列
    judgeIsShow(column){
      let exist=this.allTableLabel.filter(item=> item.label==column);
      let isShow;
      if (exist.length==0){
        isShow=true
      }else{
        isShow= exist[0].isShow;
      }
      return isShow;
    },

 主要逻辑就是通过改变checkBox的选中和取消同步列的显示和隐藏  这个地方是根据两个数组中的label属性进行判断的  两者的label的值要保持一致。

效果图如下:

列拖拽的步骤思路:

        一、要借助第三方插件Sortable.js

        二、主要是改变table遍历的列的顺序

<el-table
      v-loading="loading"
      :data="purchaseList"
      row-key="id"
      border
      ref="purchaseTable"
      @selection-change="handleSelectionChange"
    >


      <template
        v-for="column in tableColumns">
        <el-table-column
          v-if="judgeIsShow(column.label)"
          :key="column.id"
          :prop="column.prop"
          :class-name="column.isDrag"
          :label="column.label"
          :align="column.align"
          :type="column.type"
          :width="column.width"
        >
                  <template v-if="column.scope=='scope'" scope="scope">
                    <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
                  </template>
                  <template v-else-if="column.scope=='slot-scope'" slot-scope="scope">
                    {{scope.row.contractNum}}/{{getUnit(scope.row.quantityUnit)}}
                  </template>
                  <template v-else-if="column.scope=='ClientTag'" slot-scope="scope">
                    <ClientTag :value="scope.row.contractId" :flag="flag" :view="table"/>
                  </template>


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

import Sortable from "sortablejs";
import draggable from "vuedraggable";
export default {
  name: "Purchase",
  components: {
    draggable,
    Sortable,
  },

 data() {
    return {

      table:"productTable",
      flag:"contractProducts",
      //elementui测试
      tableColumns:[
        {id:"0",type:"selection",width:"55",align:"center"},
        {id:"1",type:"index",label:"序号",align:"center",scope:"scope"},
        {id:"2",label:"采购合同号",prop:"contractNo",align:"center",isDrag:"drag"},
        {id:"3",label:"原产国",prop:"countryName",align:"center",isDrag:"drag"},
        {id:"4",label:"产品",prop:"productName",align:"center",isDrag:"drag",scope:"ClientTag"},
        {id:"5",label:"合同总数量",prop:"contractNum,quantityUnit",isDrag:"drag",align:"center",scope: "slot-scope"},
        {id:"6",label:"合同总金额",prop:"contractPrice",align:"center"},
      ],

//elementui的table所有的表头数据
      allTableLabel:[],

mounted() {
    this.columnDrop();
  },

methods: {

    //列拖拽
    columnDrop(){
      //const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
      const wrapperTr = this.$refs.purchaseTable.$el.querySelector('.el-table__header-wrapper tr');
      const that=this;
      this.sortable = Sortable.create(wrapperTr, {
        animation: 180,
        delay: 30,
        draggable:".drag",
        onEnd: evt => {
          if (this.tableColumns[evt.newIndex].isDrag!=undefined) {


            const oldItem = this.tableColumns[evt.oldIndex]
            this.tableColumns.splice(evt.oldIndex, 1);
            this.tableColumns.splice(evt.newIndex, 0, oldItem)

            //改变两个列的id属性之后  表格的数据才进行跟新
            this.tableColumns[evt.oldIndex].id=parseTime(new Date(), "{y}{m}{d}{h}{i}{s}")+"1"    
            this.tableColumns[evt.newIndex].id=parseTime(new Date(), "{y}{m}{d}{h}{i}{s}")+"2"       
      }else{

          }
        },
      });
    },
}

 效果图如下显示:

到此为止分别引用的时候是没问题的。

但是两者整合的时候有BUG

主要原因是因为拖拽的是显示的列,而重排的是全部的列,同时evt.oldIndex和evt.newIndex是显示列拖拽的column的index  这个地方用splice方法重排所有的column的index  排序的时候就出现乱排、不排的现象。

解决思路:

获得拖拽列的两个列的label  然后遍历全部的列  要是label相等的就返回全部列其中两个相等label列的下标  然后重排这两个列就行。

具体代码优化如下:

//列拖拽
    columnDrop(){
      //const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
      const wrapperTr = this.$refs.purchaseTable.$el.querySelector('.el-table__header-wrapper tr');
      const tableColumn=this.$refs.purchaseTable.columns;
      let oldLabel;
      let newLabel;
      let oldIndex;
      let newIndex;
      let count=0;
      const that=this;
      this.sortable = Sortable.create(wrapperTr, {
        animation: 180,
        delay: 30,
        draggable:".drag",
        onEnd: evt => {
          if (this.tableColumns[evt.newIndex].isDrag!=undefined) {

            oldLabel=this.$refs.purchaseTable.columns[evt.oldIndex].label;
            newLabel=this.$refs.purchaseTable.columns[evt.newIndex].label;

            for (let i=0;i<that.tableColumns.length;i++){
              if (that.tableColumns[i].label!=undefined&&that.tableColumns[i].label==newLabel)
                newIndex=i;

              };

              for (let i=0;i<that.tableColumns.length;i++){
                if (that.tableColumns[i].label!=undefined&&that.tableColumns[i].label==oldLabel)
                  oldIndex=i;
              }

            const oldItem = this.tableColumns[oldIndex]
            this.tableColumns.splice(oldIndex, 1);
            this.tableColumns.splice(newIndex, 0, oldItem)

            this.tableColumns.forEach((item)=>{
              if(item.label==newLabel||item.label==oldLabel){
                item.id=parseTime(new Date(), "{y}{m}{d}{h}{i}{s}") + (++count)
                console.log(item.label)
              }
            })
      }else{

          }
        },
      });
    },

整体效果图如下:

 

以上代码只是粘贴了主要部分,有什么好的方法欢迎交流

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

ElementUI实现el-table列的显示与隐藏和列拖拽(RuoYi分离版) 的相关文章

随机推荐

  • 定制android ROM禁止SIM卡状态改变系统弹出提示框

    按上一篇文章 搭建可修改android 系统的环境 http blog csdn net karts article details 64124098 SIM卡状态改变系统弹出提示框 是在 Keyguard 这个apk里面进行的 1 cop
  • go语言基础-----19-----Context使用原则、接口、派生上下文(select的多路复用可以参考这里理解更好)

    1 Go语言Context介绍 为什么需要 Context 每一个处理都应该有个超时限制 需要在调用中传递这个超时 比如开始处理请求的时候我们说是 3 秒钟超时 那么在函数调用中间 这个超时还剩多少时间了 需要在什么地方存储这个信息 这样请
  • 安全意识培训:如何提高员工网络安全意识?

    随着网络技术的不断发展和应用 网络安全已经成为企业必须关注和重视的问题 尤其是在今天 企业数字化转型的大背景下 网络安全问题日益凸显 对于企业而言 员工是企业安全的第一道防线 提高员工的网络安全意识已经成为企业安全管理的关键所在 本文将从以
  • 【实践篇】推荐算法PaaS化探索与实践

    作者 京东零售 崔宁 1 背景说明 目前 推荐算法部支持了主站 企业业务 全渠道等20 业务线的900 推荐场景 通过梳理大促运营 各垂直业务线推荐场景的共性需求 对现有推荐算法能力进行沉淀和积累 并通过算法PaaS化打造通用化的推荐能力
  • Flutter图片放大(双击缩放、双指滑动缩放、拖拽)

    import dart ui import package flutter material dart import package flutter services dart import package flutter screenut
  • uniapp+vue3+ts 使用pinia报错

    hasInjectionContext is not exported by node modules vue demi lib index mjs imported by node modules pinia dist pinia mjs
  • springboot开启多线程支持

    springboot开启多线程支持 springboot默认是可以支持多线程的 配置类上加上 EnableAsync注解 就可以在想多线程支持的方法上加上 Async该方法就可以自持多线程了 配置类 配置线程池 import org spr
  • 接口失败--net::ERR_HTTP2_PROTOCOL_ERROR 200,无法加载响应数据

    问题 接口报错 net ERR HTTP2 PROTOCOL ERROR 200 无法加载响应数据 后端返回固定一条数据的 可以正常下载导出 一般数据返回为100KB 接口报错 不明原因 解决 关闭前端配置访问网页的https 接口正常 还
  • 相机IO硬件输入输出

    工作那么久了不怎么用硬件触发 今天恶补一下 干什么用的 通过IO输入来触发相机拍照 或者通过相机的IO输出来触发光源 来一波参考网页 1 Basler相机硬触发的接线方法 2 PNP NPN与PLC 你还在傻傻分不清楚吗 3 BASLAR相
  • Centos系统中mongodb的安装详解

    1 mongodb安装 MongoDB的下载网址 Download MongoDB Community Server MongoDB 将下载的压缩包文件上传到centos系统中 可以直接使用rz scp或者可视化工具上传 解压缩文件 Mon
  • Python中sklearn版本的升级

    调用sklearn的impute时 发现sklearn中没有impute的模块 from sklearn impute import SimpleImputer 报错 ModuleNotFoundError No module named
  • Python 数据分析与可视化实战

    一 Python环境搭建与配置 Python作为一门优秀的编程语言 受到很多程序员和编程爱好者的青睐 近年来 Python还在办公领域大展拳脚 许多白领纷纷加入了学习Python的行列 这是因为Python在数据的采集 处理 分析与可视化方
  • 关于C++匿名命名空间

    C 另外有一种匿名的命名空间 来保证生成的符号是局部的 这样对于匿名空间中的变量等 外部都是不可见的 test3 cpp static void bar namespace 匿名的命名空间 float bar2 int foo test4
  • java类的加载过程

    Java 类加载机制 类从被加载到JVM中开始 到卸载为止 整个生命周期包括 加载 验证 准备 解析 初始化 使用和卸载七个阶段 其中类加载过程包括加载 验证 准备 解析和初始化五个阶段 类的加载过程 png 类的加载过程 加载 1 通过类
  • Unity中GetAxisRaw和GetAxis的区别

    GetAxis带有变化程度 GetAxisRaw更精准 在Unity中 Input GetAxis和Input GetAxisRaw函数都用于读取输入轴的值 但它们有一些区别 GetAxis函数返回的值是经过平滑处理的 即它会在一定时间内将
  • vpn原理

    1 VPN原理 VPN是虚拟专用网络的简称 简单的说就是利用公用网络架设专用网络 当我们打开VPN的时候 VPN就会在电脑上虚拟一个IP地址 当电脑要传输数据包时 VPN会对这个数据包进行加密 发出数据包的地址是VPN虚拟出来的地址 而接受
  • WPF的RenderTransform特效

    RenderTransform特效 变形 WPF中的变形 RenderTransform 类是为了达到直接去改变某个Silverlight对象的形状 比如缩放 旋转一个元素 的目的而设计的 RenderTransform包含的变形属性成员就
  • 操作系统题库

    第一章作业一 一 单选题 共5题 25 0分 操作系统的 管理部分负责对进程进行调度 A 存储器 B 设备 C 文件 D 处理机 正确答案 D 我的答案 D 下面操作系统 要保证系统有较高的吞吐能力 A 批处理系统 B 分时系统 C 网络操
  • Linux-文本处理

    一 字段截取 1 1 cut字段提取命令 格式 cut d 间隔符 f 列号 c 字符 cut 选项 文件名 区别 grep是行提取命令 cut是列提取命令 d 指定分隔符类型 f 指定打印第几列 c 按字符分割 按照单个字符进行分割 比如
  • ElementUI实现el-table列的显示与隐藏和列拖拽(RuoYi分离版)

    显示隐藏步骤思路 一 table要实现v for循环添加列的操作 二 给列添加v if属性 方法返回当前列是否显示隐藏 在RightToolBar添加列显示隐藏的图标控件