element plus 表el-table的多级表头/动态表头处理

12 篇文章 1 订阅
5 篇文章 1 订阅

我写技术文章没那么多废话,直接上代码:
1.效果预览:
在这里插入图片描述
其中,superColumns与columns是根据后端返回的数据决定的,是动态的。
2.在vue里面的代码:

<el-table
          ref="multipleTableRef"
          v-loading="state.loading"
          :data="list"
          cell-style="text-align: center"
          header-cell-style="text-align: center"
        >
        
          <el-table-column label="学院" prop="gradeName" min-width="180" show-overflow-tooltip>
            <template #default="{ row }">
              <span>{{row.collegeName?row.collegeName:'没有学院'}}</span>
            </template>
          </el-table-column>
          <el-table-column :label="superColumn == '总计'?superColumn:superColumn+'级'" v-for="(superColumn,idx) in state.superColumns" :key="idx">
            <el-table-column
              :label="superColumn == '总计'?'总学生':'年级学生'"
              prop="data"
              min-width="120"
              :show-overflow-tooltip="true"
            >
              <template #default="{ row }">
                <span>{{ row[superColumn].total?row[superColumn].total:0 }}</span>
              </template>
            </el-table-column>
            <el-table-column label="困难学生">
              <el-table-column v-for="(column,idx) in state.columns" :key="idx"
                :label="getColumnName(column)"
                :prop="column"
                min-width="120"
                :show-overflow-tooltip="true"
              >
                <template #default="{ row }">
                  <span>{{ row[superColumn][column]?row[superColumn][column]:0 }}</span>
                </template>
              </el-table-column>
              <el-table-column
                label="合计"
                prop="data"
                min-width="120"
                :show-overflow-tooltip="true"
              >
                <template #default="{ row }">
                  <span>{{ row[superColumn].totalApplyQty }}</span>
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column
              v-if="superColumn != '总计'"
              label="困难学生比例"
              prop="data"
              min-width="120"
              :show-overflow-tooltip="true"
            >
              <template #default="{ row }">
                <span>{{ row[superColumn].totalApplyQty?(row[superColumn].totalApplyQty * 100 / row[superColumn].total).toFixed(2):"0.00" }}%</span>
              </template>
            </el-table-column>
            <el-table-column label="困难学生比例" v-if="superColumn == '总计'">
              <el-table-column v-for="(column,idx) in state.columns" :key="idx"
                :label="getColumnName(column)"
                :prop="column"
                min-width="120"
                :show-overflow-tooltip="true"
              >
                <template #default="{ row }">
                  <span>{{ row[superColumn].total?(row[superColumn][column]*100 / row[superColumn].total).toFixed(2):"0.00" }}%</span>
                </template>
              </el-table-column>
              <el-table-column
                label="合计"
                prop="data"
                min-width="120"
                :show-overflow-tooltip="true"
              >
                <template #default="{ row }">
                  <span>{{ row[superColumn].total?(row[superColumn].totalApplyQty *100 / row[superColumn].total).toFixed(2):"0.00" }}%</span>
                </template>
              </el-table-column>
            </el-table-column>
          </el-table-column>
        </el-table>

3.ts里面代码:

// 列表 + 模拟数据(后端返回的数据结构)
const list = ref<any>([
        {
            "title": "2020",
            "data": [
                {
                    "collegeNo": "0207",
                    "collegeName": "艺术学院",
                    "total": 1045,
                    "totalApplyQty": 1,
                    "KNDJ001": 0,
                    "KNDJ002": 0,
                    "KNDJ003": 0
                },
                {
                    "collegeNo": "0206",
                    "collegeName": "智能制造与能源工程学院",
                    "total": 1364,
                    "totalApplyQty": 1,
                    "KNDJ001": 0,
                    "KNDJ002": 0,
                    "KNDJ003": 0
                }
            ]
        },
        {
            "title": "2019",
            "data": [
                {
                    "collegeNo": "0206",
                    "collegeName": "智能制造与能源工程学院",
                    "total": 1364,
                    "totalApplyQty": 4,
                    "KNDJ001": 0,
                    "KNDJ002": 0,
                    "KNDJ003": 0
                }
            ]
        },
        {
            "title": "2018",
            "data": []
        },
        {
            "title": "总计",
            "data": [
                {
                    "collegeNo": "0206",
                    "collegeName": "智能制造与能源工程学院",
                    "total": 1364,
                    "totalApplyQty": 5,
                    "KNDJ001": 0,
                    "KNDJ002": 0,
                    "KNDJ003": 0
                },
                {
                    "collegeNo": "0207",
                    "collegeName": "艺术学院",
                    "total": 1045,
                    "totalApplyQty": 1,
                    "KNDJ001": 0,
                    "KNDJ002": 0,
                    "KNDJ003": 0
                }
            ]
        }
    ]) 

其中,KNDJ001、KNDJ002、KNDJ003、title是会变动的,就像KNDJ001、KNDJ002、KNDJ003其实是困难生的认定等级的编码,这次是KNDJ001、KNDJ002、KNDJ003,下次可能是张三李四王五。最后从代码库拉取的数据与KNDJ001、KNDJ002、KNDJ003等匹配获取它们代表的含义如:特别困难、困难、一般困难
4.对接口返回的数据处理 ,对第3条中的list 处理:

const state:any = reactive({
  columns:[],//动态表头的名
  superColumns:[],//动态表头的名 最高级
  kndjList:[],//困难等级数组
})
//处理学生处的数据
const dealXSCList = ( list :any) => {
  list.reverse();//为什么先反转,是因为返回数据都会有“总计”这一条数据,且它是数据最多的,以它为处理模板
  state.columns = [];
  state.superColumns = [];
  let arr:any = [];
  let templateData:any = {};//记录用来填充没数据的模板
  for(let i = 0; i < list.length ; i++){
    let item = list[i].data;
    if(state.superColumns.indexOf(list[i].title) < 0)state.superColumns.push(list[i].title);
    if(item.length > 0){
      for ( let j = 0; j < item.length ; j++){
        if(!arr[j]) {
          arr[j]= {};
          arr[j].collegeName = item[j].collegeName;
          arr[j][list[i].title] = item[j];
          templateData = cloneDeep(item[j]);
        }else{
          for(let n = 0;  n < arr.length ; n++){
            arr[n][list[i].title] = cloneDeep(clearDefaultData(templateData));
            if(arr[n].collegeName == item[j].collegeName){
              arr[n][list[i].title] = item[j];
            }
          }
        }
        for(let key in item[j]){
          if(key != 'collegeNo' && key != 'collegeName'){
            if(key != 'total' && key != 'totalApplyQty' && key != 'gradeName'){
              if(state.columns.indexOf(key) < 0) state.columns.push(key);
            }
          }
        }
      }
    }else{//缺的数据补0
      for(let n = 0; n < arr.length ; n++){
        arr[n][list[i].title] = cloneDeep(clearDefaultData(templateData));
      }
    }
  }
  console.log("学生处的数据",state.superColumns,state.columns,arr);
  //所有的数据总计
  let firstData:any = {};
  firstData.collegeName = "总计";
  for(let i = 0; i < arr.length ; i++){
    for(let key in arr[i]){
      if(key != 'collegeName'){
        if(!firstData[key])firstData[key]={};
        for(let ky in arr[i][key]){
          if(ky != 'collegeName' && ky != 'collegeNo'){
            if(!firstData[key][ky]) firstData[key][ky] = 0;
            firstData[key][ky] += arr[i][key][ky]*1
          }
        }
      }
    }
  }
  state.superColumns.sort().reverse();
  if(arr.length == 0){//当没有长度时候 清空是防止报错
    state.columns = [];
    state.superColumns = [];
  }else{
    arr.reverse();
    arr.unshift(firstData)
  }
  console.log("学生处的数据2",state.superColumns,state.columns,arr);
  return arr
}
//克隆数据
const cloneDeep = (row:any) =>{
  if(!row) return;
  return JSON.parse(JSON.stringify(row));
}
//把默认数据置为0
const clearDefaultData = ( row :any)=>{
  if(!row) return;
  for(let key in row){
    if(key != 'collegeName' && key != 'collegeNo' && key != 'gradeName'){
      row[key] = 0;
    }else{
      row[key] = "";
    }
  }
  return row
}  

//获得表头名
const getColumnName = (column: any)=>{
  let name = "无";
  if(column && state.kndjList.length > 0){
    state.kndjList.forEach((item:any)=>{
      if(item.dataCode == column){
        name = item.dataName;
      }
    })
  }
  return name;
}

其中,superColumns记录的是顶部的动态表头,columns 记录的是困难等级的动态表头(后端可能设置)。
处理的结果:
在这里插入图片描述
为什么把数据像总计、2020、2019、2018处理成key?是方便数据循环时,通过 row[superColumn]“ 可以拿到对应年的数据,再通过”row[superColumn].total“或者“row[superColumn][column] ”拿到对应的具体值。
处理的数据大概结构:

//list被处理后的结构:
[
	{
		”总计“:{
			"collegeNo":"0207",
			"collegeName":"艺术学院",
			"total":1045,
			"totalApplyQty":1,
			"KNDJ001":0,
			"KNDJ002":0,
			"KNDJ003":0
		},2020“:{
			"collegeNo":"",
			"collegeName":"",
			"total":1045,
			"totalApplyQty":1,
			"KNDJ001":0,
			"KNDJ002":0,
			"KNDJ003":0
		},2019“:{
			"collegeNo":"",
			"collegeName":"",
			"total":1045,
			"totalApplyQty":1,
			"KNDJ001":0,
			"KNDJ002":0,
			"KNDJ003":0
		},
	},
	{
		”总计“:{
			"collegeNo":"0206",
			"collegeName":"计算机学院",
			"total":1045,
			"totalApplyQty":1,
			"KNDJ001":0,
			"KNDJ002":0,
			"KNDJ003":0
		},2020“:{
			"collegeNo":"",
			"collegeName":"",
			"total":1045,
			"totalApplyQty":1,
			"KNDJ001":0,
			"KNDJ002":0,
			"KNDJ003":0
		},2019“:{
			"collegeNo":"",
			"collegeName":"",
			"total":1045,
			"totalApplyQty":1,
			"KNDJ001":0,
			"KNDJ002":0,
			"KNDJ003":0
		},
	},
]

5.最终的项目效果:
在这里插入图片描述
如果不处理数据排序与数据补0,核心逻辑dealXSCList 代码可以20行搞定
6.感谢
如果觉得写得好,记得收藏哦 ~ (O_O) ~

  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Element Plus 的 el-table-v2 组件支持自定义多级表头,可以通过 el-table-column 的 children 属性来实现。具体步骤如下: 1. 在 el-table-column 中设置 prop 和 label 属性,用于显示表头名称和对应的数据字段。 2. 如果需要设置多级表头,可以在 el-table-column 中设置 children 属性,并在其中嵌套新的 el-table-column 组件,重复步骤1。 3. 如果需要合并表头单元格,可以在 el-table-column 中设置 rowspan 和 colspan 属性。 4. 如果需要自定义表头样式,可以在 el-table-column 中设置 headerStyle 属性。 下面是一个示例代码,展示了如何使用 el-table-v2 自定义多级表头: ``` <template> <el-table :data="tableData"> <el-table-column prop="name" label="姓名"></el-table-column> <el-table-column label="成绩"> <el-table-column prop="math" label="数学"></el-table-column> <el-table-column prop="english" label="英语"></el-table-column> <el-table-column prop="chinese" label="语文"></el-table-column> </el-table-column> <el-table-column prop="total" label="总分" rowspan="2"></el-table-column> </el-table> </template> <script> import { ref } from "vue"; import { ElTable, ElTableColumn } from "element-plus"; export default { components: { ElTable, ElTableColumn, }, setup() { const tableData = ref([ { name: "张三", math: 80, english: 90, chinese: 85, total: 255 }, { name: "李四", math: 75, english: 85, chinese: 90, total: 250 }, ]); return { tableData, }; }, }; </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值