显示隐藏步骤思路:

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

          }
        },
      });
    },

整体效果图如下:

 

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

Logo

快速构建 Web 应用程序

更多推荐