vue el-table实现动态表头

一、前言

众所周知,element-ui中有一个表格组件el-table,用于展示多条结构类似的数据。之前遇到过一个需求,要手动控制el-table的表头显示。就是假如table表格一共有10列数据,可以通过设置勾选,决定显示多少列。

二、代码

为了代码的复用性,将配置页面单独抽成了组件,所以代码中会有组件之间传值
父组件(表格页面)

<template>
  <div class="testTable">
    <div class="settingIcon">
      <i class="el-icon-setting" @click="showSetting" />
    </div>
    <el-table :data="tableData" style="width: 100%">
      <el-table-column
        v-for="item in showTableColumn"
        :key="item.prop"
        :fixed="item.fixed"
        :align="item.align"
        :prop="item.prop"
        :min-width="item.minWidth"
        :width="item.width"
        :show-overflow-tooltip="item.tooltip"
        :resizable="item.resizable"
        :label="item.label"
      />
    </el-table>
    <!-- 配置页面 -->
    <key-setting
      :visible.sync="isSetting"
      :data-arr="AllPropertyArrForManage"
      :check-list="checkProp"
      :default-arr="DefaultPropertyArrForManage"
      @confirm="handleConfirm"
    />
  </div>
</template>

<script>
import keySetting from '@/components/keySetting/index.vue'
export default {
    
    
  components: {
    
     keySetting },
  data() {
    
    
    return {
    
    
      showTableColumn: [],
      tableData: [
        {
    
    
          date: '2016-05-02',
          age: '28',
          gender: '男',
          name: '王虎',
          address: '上海市普陀区金沙江路 1518 弄'
        },
        {
    
    
          date: '2016-05-04',
          age: '20',
          gender: '男',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄'
        },
        {
    
    
          date: '2016-05-01',
          age: '25',
          gender: '男',
          name: '王二虎',
          address: '上海市普陀区金沙江路 1519 弄'
        },
        {
    
    
          date: '2016-05-03',
          age: '40',
          gender: '男',
          name: '王大虎',
          address: '上海市普陀区金沙江路 1516 弄'
        }
      ],
      isSetting: false,
      AllPropertyArrForManage: [
        {
    
     prop: 'date', label: '日期', minWidth: '120',
          align: 'center',
          tooltip: true,
          resizable: true },
        {
    
     prop: 'age', label: '年龄', minWidth: '120',
          align: 'center',
          tooltip: true,
          resizable: true },
        {
    
     prop: 'gender', label: '性别', minWidth: '120',
          align: 'center',
          tooltip: true,
          resizable: true },
        {
    
     prop: 'name', label: '姓名', minWidth: '120',
          align: 'center',
          tooltip: true,
          resizable: true },
        {
    
     prop: 'address', label: '地址', minWidth: '120',
          align: 'center',
          tooltip: true,
          resizable: true }
      ], // 所有字段
      checkProp: [], // 选中字段
      DefaultPropertyArrForManage: [
        'name', 'age'
      ] // 默认选中字段
    }
  },
  mounted() {
    
    
    this.dealTableColumn(this.checkProp)
  },
  methods: {
    
    
  // 点击配置图标
    showSetting() {
    
    
      this.isSetting = !this.isSetting
      if (this.isSetting) {
    
    
        this.checkProp = this.DefaultPropertyArrForManage
      }
    },
    // 提交确定事件 实际工作中会调接口
    handleConfirm(val) {
    
    
      this.checkProp = val
      this.dealTableColumn(this.checkProp)
    },
    // 重新渲染table表格
    dealTableColumn(arr) {
    
    
      this.showTableColumn = []
      this.AllPropertyArrForManage.forEach((item) => {
    
    
        if (arr.indexOf(item.prop) > -1) {
    
    
          this.showTableColumn.push(item)
        }
      })
    }
  }
}
</script>

子组件(配置页面)

<template>
  <div class="wrapper">
    <el-card class="box-card" :style="{'width': visible ? '230px' : '0', 'opacity': visible ? '1' : '0'}">
      <div slot="header" style="min-width: 200px">
        <span>字段配置</span>
        <span class="fr close-btn" @click="$emit('update:visible', false)">×</span>
      </div>
      <div>
        <el-checkbox v-model="checkAll" label="a" :indeterminate="isIndeterminate" @change="selectAll">全选</el-checkbox>
        <el-checkbox-group v-model="realList" class="check-list" @change="handleCheckedChange">
          <el-checkbox v-for="item in dataArr" :key="item.prop" :label="item.prop" :disabled="item.prop=='name'">{
    
    {
    
     item.label }}</el-checkbox>
        </el-checkbox-group>
      </div>
      <div class="footer" style="min-width: 200px">
        <el-button type="primary" size="small" :disabled="realList.length < 1" @click="confirm">确定</el-button>
        <el-button size="small" @click="reset">重置</el-button>
        <el-button size="small" @click="cancel">取消</el-button>
      </div>
    </el-card>
  </div>
</template>

<script>
export default {
    
    
  name: 'KeySetting',
  props: {
    
    
    visible: {
    
    
      type: Boolean,
      default: false
    },
    dataArr: {
    
    
      type: Array,
      default: () => []
    },
    checkList: {
    
    
      type: Array,
      default: () => []
    },
    defaultArr: {
    
    
      type: Array,
      default: () => []
    }
  },
  data() {
    
    
    return {
    
    
      checkAll: false,
      realList: [],
      isIndeterminate: true
    }
  },
  watch: {
    
    
    checkList(val) {
    
    
      this.realList = val
      if (val.length === this.dataArr.length) {
    
    
        this.isIndeterminate = false
        this.checkAll = true
      }
    }
  },
  methods: {
    
    
  // 全选按钮
    selectAll(val) {
    
    
      this.realList = val ? this.dataArr.map(item => item.prop) : this.defaultArr
      if (val) {
    
    
        this.isIndeterminate = false
      } else {
    
    
        this.isIndeterminate = true
      }
    },
    // el-checkbox选中事件
    handleCheckedChange(value) {
    
    
      const checkedCount = value.length
      this.checkAll = checkedCount === this.dataArr.length
      this.isIndeterminate = checkedCount > 0 && checkedCount < this.dataArr.length
    },
    // 点击确定
    confirm() {
    
    
      this.$emit('confirm', this.realList)
      this.$emit('update:visible', false)
    },
    // 点击重置
    reset() {
    
    
      this.realList = [...this.defaultArr]
      this.isIndeterminate = true
      this.checkAll = false
    },
    // 点击取消
    cancel() {
    
    
      this.realList = this.checkList
      this.$emit('update:visible', false)
    }
  }
}
</script>

以上代码不包含css样式,可根据实际情况自行添加

三、效果如下

1.正常页面:全部列数据
在这里插入图片描述
2.配置页面
在这里插入图片描述
3.动态配置
在这里插入图片描述

四、其他

上面代码中演示的数据是固定,实际工作中会有后端的接口支持,这样数据更新会很方便。
欢迎参考!

猜你喜欢

转载自blog.csdn.net/qq_45093219/article/details/127122803