vue iview table实现动态自定义表头

发布时间 2023-04-10 17:20:46作者: ysx_小鱼

一、前言

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

二、代码

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

<template>
  <div>
    <!-- 渲染table表格 -->
    <TableComponent :allColList='allColList' :tableData='tableData' :defaultCheckList='defaultCheckList' @confirm="handleConfirm"></TableComponent>
  </div>
</template>

<script>
import TableComponent from '@/components/TableComponent.vue'
export default {
  name:'tableShow',
  components:{
    TableComponent
  },
  data(){
    return {
      // 所有表格列
      allColList: [
        {
          type: "selection",
          key: "selection",
          width: 60,
          align: "center",
        },
        {
          title: "入口ID",
          key: "enterId",
          minWidth: 120,
          align: "center",
          tooptip: true,
        },
        {
          title: "渠道",
          key: "channel",
          minWidth: 120,
          align: "center",
        },
        {
          title: "品牌",
          key: "brand",
          minWidth: 120,
          align: "center",
        },
        {
          title: "入口名",
          key: "enterName",
          minWidth: 120,
          align: "center",
          tooptip: true,
        },
        {
          title: "状态",
          key: "status",
          minWidth: 120,
          align: "center",
        },
        {
          title: "更新人",
          key: "updatedBy",
          minWidth: 120,
          align: "center",
        },
      ],
      //默认列
      defaultCheckList:["enterId","channel","enterName"],
      tableData: [
        {
          enterId: "1234wert",
          channel: "手机",
          brand: "小米",
          enterName: "个性化视频专辑",
          status: "上线",
          updatedBy: "admin",
        },
      ],
    }
  },
  methods:{
    // 提交确定事件 实际工作中会调接口
    handleConfirm(val) {
      this.defaultCheckList = val;
    },
  }
}
</script>

子组件(配置页面)

<template>
  <div>
    <div class="dropdown">
      <Dropdown trigger="custom" placement="bottom-end" :visible="visible">
        <a href="javascript:void(0)" @click="handleOpen">
          自定义Table列
          <Icon type="ios-arrow-down"></Icon>
        </a>
        <DropdownMenu slot="list" style="width: 240px">
          <div style="padding: 10px 15px;">
            <div style="border-bottom: 1px solid #e9e9e9;padding-bottom:6px;margin-bottom:6px;">
              <Checkbox
                :indeterminate="indeterminate"
                :value="checkAll"
                @click.prevent.native="handleCheckAll"
              >全选</Checkbox>
            </div>
            <CheckboxGroup
              v-model="checkAllGroup"
              @on-change="checkAllGroupChange"
            >
              <Checkbox v-for="item in allCheckList" :key='item.key' :label="item.key">{{item.title}}</Checkbox>
            </CheckboxGroup>
          </div>
          <div class="btnGroup">
            <Button type="primary" @click="confirm" :disabled="checkAllGroup.length < 1">确认</Button>
            <Button @click="handleClose">关闭</Button>
          </div>
        </DropdownMenu>
      </Dropdown>
    </div>
    <Table ref="table" border :columns="showColList" :data="tableData"> </Table>
  </div>
</template>

<script>
export default {
  name: "tableComponent",
  data() {
    return {
      //实际显示的表格列
      showColList: [],
      //是否显示配置弹出窗
      visible: false,
      indeterminate: true,
      checkAll: false,
      // 选中表格列
      checkAllGroup: [],
      //所有供选择的项
      allCheckList:[],
      // 默认显示的列
      defaultColCheckList: [],
    };
  },
  props:{
    //所有table列
    allColList:{   
      type:Array,
      require:true
    },
    //table数据
    tableData:{   
      type:Array,
      default:() => []
    },
    //默认被选择的项
    defaultCheckList:{
      type:Array,
      default:() => []
    }
  },
  computed: {},
  created(){
    console.log('我是生命钩子函数created');
    this.init();
  },
  watch:{
    defaultCheckList(newValue, oldValue){
      console.log('我是监听器函数checkList');
      console.log(newValue)
      console.log(oldValue)
      this.init();
    }
  },
  methods: {
    init(){
      console.log('我是初始化方法init');
      this.allCheckList = this.allColList.filter(item => {
        if(!item.type){
          return item
        }
      })
      if(this.defaultCheckList.length > 0){
        this.defaultColCheckList = this.defaultCheckList;
      }else{
        this.defaultColCheckList = this.allCheckList.map(item => {
          return item.key
        })
      }
      this.dealTableColumn(this.defaultColCheckList);
    },
    /**
     * 重新渲染table表格
     */ 
    dealTableColumn(arr) {
      this.showColList = [];
      this.allColList.forEach((item) => {
        if (arr.indexOf(item.key) > -1) {
          this.showColList.push(item);
        }
      });
    },
    /**
     * 显示配置弹窗
    */
    handleOpen() {
      this.visible = true;
      this.checkAllGroup = this.defaultColCheckList;
      if(this.checkAllGroup.length == this.allCheckList.length){
        this.indeterminate = false;
        this.checkAll = true;
      }
    },
    /**
     * 隐藏配置弹窗
    */
    handleClose() {
      this.visible = false;
      this.checkAllGroup = [];
    },
    /**
     * 全选时处理逻辑
    */
    handleCheckAll() {
      if (this.indeterminate) {
        this.checkAll = false;
      } else {
        this.checkAll = !this.checkAll;
      }
      this.indeterminate = false;

      if (this.checkAll) {
        this.checkAllGroup = this.allColList.map(item => {
          return item.key
        })
      } else {
        this.checkAllGroup = [];
      }
    },
    /**
     * 选项发生变化时处理逻辑
    */
    checkAllGroupChange(data) {
      if (data.length === this.allCheckList.length) {
        this.indeterminate = false;
        this.checkAll = true;
      } else if (data.length > 0) {
        this.indeterminate = true;
        this.checkAll = false;
      } else {
        this.indeterminate = false;
        this.checkAll = false;
      }
    },
    /**
     * 确认提交配置项
    */
    confirm(){
      // this.dealTableColumn(this.checkAllGroup);
      // this.defaultColCheckList = this.checkAllGroup;
      this.$emit('confirm', this.checkAllGroup)
      this.visible = false;
    }
  },
};
</script>

<style scoped>
.dropdown {
  display: flex;
  justify-content: right;
  margin:20px;
}
.ivu-checkbox-group-item{
  display: block;
  margin-top: 8px;
}
.btnGroup{
  text-align: right;  
  margin-bottom: 10px;
}
.btnGroup button{
  margin-right: 10px;
}
</style>

三、效果如下