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

显示隐藏步骤思路:

一、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{

          }
        },
      });
    },

整体效果图如下:

 

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

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
这段代码是一个Vue组件中的模板代码,包含了一个el-button和一个自定义组件right-toolbarel-button是一个Element UI库中的组件,用于创建一个按钮。它具有如下属性: - plain:按钮是否为朴素按钮。 - formDialogRef:指定一个表单对话框的ref。 - :disabled:按钮是否为禁用状态,这里使用了v-bind指令动态绑定了一个名为multiple的变量。 - icon:按钮的图标。 - type:按钮的类型,这里设置为primary类型。 - @click:按钮的点击事件处理函数,这里调用了名为handleDelete的函数并传递了一个名为selectObjs的参数。 - {{ $t('common.delBtn') }}:按钮的显示文字,使用了Vue的模板语法。 right-toolbar是一个自定义的组件,它具有如下属性: - v-model:showSearch:使用了Vue的双向绑定语法,将showSearch属性与父组件中的一个名为showSearch的变量进行双向绑定。 - :export:指定了导出Excel的接口地址,这里使用了v-bind指令动态绑定了一个名为security.check_checkEvaluate_export的值。 - @exportExcel:自定义组件中的导出Excel事件处理函数,该事件由自定义组件触发并将导出Excel所需的参数传递给父组件中的exportExcel方法。 - @queryTable:自定义组件中的查询表格事件处理函数,该事件由自定义组件触发并将查询表格所需的参数传递给父组件中的getDataList方法。 总体来说,这段代码是一个包含了两个按钮(一个是element UI中的按钮,一个是自定义的按钮)的组件模板,可以实现删除数据和导出Excel的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值