vue el-table implements dynamic header

I. Introduction

As we all know, there is a table component el-table in element-ui, which is used to display multiple pieces of data with similar structure. I have encountered a need before to manually control the header display of el-table. That is, if the table has a total of 10 columns of data, you can decide how many columns to display by setting the check box.

2. Code

For the sake of code reusability, the configuration page is extracted into separate components, so there will be values ​​passed between components in the code.
Parent component (table page)

<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>

Subcomponents (configuration page)

<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>

The above code does not include css styles, you can add them according to the actual situation.

3. The effect is as follows

1. Normal page: all column data
Insert image description here
2. Configuration page
Insert image description here
3. Dynamic configuration
Insert image description here

4. Others

The data demonstrated in the above code is fixed. In actual work, there will be back-end interface support, so data updates will be very convenient.
Welcome for reference!

Guess you like

Origin blog.csdn.net/qq_45093219/article/details/127122803