本篇文章是优化上一篇配置表格列文章。相当于实现这种效果的第二种方式。上一篇文章地址如下:
https://segmentfault.com/a/11...

问题描述

当表格列过多的时候,产品说加一个配置列的功能吧。即勾选了,让其显示。不勾选让其隐藏。下次打开浏览器的时候,还保留上一次的表格列的显示隐藏状态。

效果图附上

代码附上

代码注释写了思路了呢,其实也很简单

子组件表格组件

<template>
  <div class="box">
    <el-table
      :data="tableData"
      border
      style="width: 100%"
      @selection-change="handleSelectionChange"
      @sort-change="sortChange"
    >
      <!-- 复选框列
              复选框列和索引列因为有的显示有的不显示,所以我们使用一个v-if去控制它,
              v-if的标识取决于父组件(引用这个组件的组件)传递过来的标识。子组件也就是
              我们封装的这个myTable组件用props接收一下又因为复选框要有勾选时间所以
              @select-change事件不能落下
       -->
      <el-table-column
        v-if="isShowCheckbox == true"
        type="selection"
        width="48"
        fixed
      ></el-table-column>
      <!-- 索引列 -->
      <el-table-column
        v-if="isShowIndex == true"
        label="序号"
        type="index"
        width="50"
        fixed
      >
      </el-table-column>
      <!-- 主内容列 
              主内容列的表头就是label,表头列对应的数据就是prop,所以父组件可以传递过来
              一个数组,里面的每一项就是label的名字和prop对应的值。通过v-for就动态了呈现了
              sortable为布尔值控制是否开启当前行的排序功能。
      -->
      <!--  我们通过父组件表头数组中的isHidden来实现中的列的显示与隐藏,当我们勾选复选框点击确定以后
            可以去更改表头数组对应项目的isHidden属性
            
            v-for和v-if不能在一块使用,会浪费性能。为了避免同时使用v-for和v-if可以再套一层template,
              template不会生成dom元素。这样的话就解决问题了 
      -->
      <template v-for="(item, index) in tableHeaderTitle">
        <el-table-column
          :prop="item.propName"
          :label="item.labelName"
          :key="index"
          :sortable="sortRule(item.isSort)"
          v-if="item.isHidden == false"
        >
        </el-table-column>
      </template>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "myTable",
  props: {
    // 父组件传递过来的表头的数组数据
    tableHeaderTitle: {
      type: Array,
      default: [],
    },
    // 父组件传递过来的表内容的数组数据
    //  注意:表头内容数据和表内容数据有关联的
    tableData: {
      type: Array,
      default: [],
    },
    // 父组件传递过来的是否展示复选框列的标识
    isShowCheckbox: {
      type: Boolean,
      default: false,
    },
    // 父组件传递过来的是否展示序号索引列的标识
    isShowIndex: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    // 勾选以后,要把勾选的这一行的数据传递给父组件,以供使用
    handleSelectionChange(checked) {
      console.log("勾选传递数据给父组件");
    },
    // 控制是否开启列的排序
    sortRule(flag) {
      if (flag == true) {
        return "custom";
      } else if (flag == false) {
        return false;
      }
    },
    // 排序
    sortChange(sortInfo) {
      console.log("排序方式", sortInfo.order);
      console.log("排序字段", sortInfo.prop);
    },
  },
};
</script>

父组件

<template>
  <div id="app">
    <!-- 简单封装一个表格的全局组件并注册使用,方便coding -->
    <my-table
      :tableHeaderTitle="tableHeaderTitle"
      :tableData="tableData"
      :isShowCheckbox="isShowCheckbox"
      :isShowIndex="isShowIndex"
    ></my-table>
    <br />
    <br />
    <br />
    <div class="setColumn">
      <el-checkbox
        v-model="item.showColumn"
        v-for="(item, index) in columnArr"
        :key="index"
        >{{ item.title }}</el-checkbox
      >
      <br />
      <el-button @click="confirm" size="mini" type="primary">确认配置列</el-button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 控制表头的显示隐藏
      columnArr: [],
      //模拟表头数组数据,实际可发请求获取,也可以前端固定这样写。
      tableHeaderTitle: [],
      // 模拟表内容数据,表内容数据要发请求获取
      tableData: [
         {
          id: "11111",
          name: "孙悟空",
          age: 500,
          gender: "男",
          height: "七尺男儿",
          weight: "三百吨",
          like: "桃子",
          address: "花果山水帘洞",
        },
        {
          id: "22222",
          name: "猪八戒",
          age: 88,
          gender: "男",
          height: "七尺男儿",
          weight: "八百吨",
          like: "肉包子",
          address: "高老庄",
        },
        {
          id: "33333",
          name: "沙和尚",
          age: 1000,
          gender: "男",
          height: "七尺男儿",
          weight: "三百吨",
          like: "鱼",
          address: "通天河",
        },
      ],
      // 是否展示复选框列
      isShowCheckbox: true,
      // 是否展示序号索引列
      isShowIndex: true,
    };
  },
  mounted() {
    // 如果修改了配置列,本地有,就用本地的修改的配置列的数据
    if (localStorage.getItem("headArr")) {
      this.columnArr = JSON.parse(localStorage.getItem("columnArr"));
      this.tableHeaderTitle = JSON.parse(localStorage.getItem("headArr"))
    } 
    // 如果没有修改配置列,就还用初始的数据,初始情况下,默认所有都显示
    else {
      this.columnArr = [
        {
          title: "姓名",
          showColumn: true,
        },
        {
          title: "年龄",
          showColumn: true,
        },
        {
          title: "性别",
          showColumn: true,
        },
        {
          title: "身高",
          showColumn: true,
        },
        {
          title: "体重",
          showColumn: true,
        },
        {
          title: "爱好",
          showColumn: true,
        },
        {
          title: "住址",
          showColumn: true,
        },
      ];
      this.tableHeaderTitle = [
        {
          propName: "name",
          labelName: "姓名",
          isSort: true,
          isHidden: false,
        },
        {
          propName: "age",
          labelName: "年龄",
          isSort: true,
          isHidden: false,
        },
        {
          propName: "gender",
          labelName: "性别",
          isSort: true,
          isHidden: false,
        },
        {
          propName: "height",
          labelName: "身高",
          isSort: false,
          isHidden: false,
        },
        {
          propName: "weight",
          labelName: "体重",
          isSort: false,
          isHidden: false,
        },
        {
          propName: "like",
          labelName: "爱好",
          isSort: false,
          isHidden: false,
        },
        {
          propName: "address",
          labelName: "住址",
          isSort: false,
          isHidden: false,
        },
      ]
    }
  },
  methods: {
    confirm() {
      /* 
          分为两个数组,选中的数组(显示数组)showshow、和未选中的数组(隐藏数组)hidehide。
              选中的要显示,未选中的去隐藏掉。选中数组和未选中数组里面存放的是title名字
              通过修改表头的isHidden属性来控制列的显示和隐藏
      */
      let showshow = [];
      let hidehide = [];
      this.columnArr.forEach((item) => {
        if (item.showColumn == true) {
          showshow.push(item.title);
        } else {
          hidehide.push(item.title);
        }
      });

      // 遍历显示数组,根据显示数组中的名字去修改对应表头数组的对象项的isHidden属性为false,
      //        为false就是不隐藏列,也就是显示列
      for (let i = 0; i < showshow.length; i++) {
        for (let j = 0; j < this.tableHeaderTitle.length; j++) {
          if (showshow[i] == this.tableHeaderTitle[j].labelName) {
            this.tableHeaderTitle[j].isHidden = false;
          }
        }
      }

      // 遍历隐藏数组,思路同上
      for (let i = 0; i < hidehide.length; i++) {
        for (let j = 0; j < this.tableHeaderTitle.length; j++) {
          if (hidehide[i] == this.tableHeaderTitle[j].labelName) {
            this.tableHeaderTitle[j].isHidden = true;
          }
        }
      }

      // 最后本地存一份,永不丢失
      localStorage.setItem("headArr", JSON.stringify(this.tableHeaderTitle));
      localStorage.setItem("columnArr", JSON.stringify(this.columnArr));
    },
  },
};
</script>

<style lang="less" scoped>
#app {
  width: 100%;
  min-height: 100vh;
  box-sizing: border-box;
  padding: 50px;
  .setColumn {
    background-color: #e9e9e9;
  }
}
</style>

水冗水孚
1.1k 声望585 粉丝

每一个不曾起舞的日子,都是对生命的辜负