elementui-table表头合并和纵向排列

本文详细介绍使用ElementUI实现复杂表格需求的技巧,包括表格合并与纵向表头的实现方式,解析数据结构并提供代码示例,适用于Vue项目中多样化表格展示需求。

使用 elementui 做项目的时候大家应该会遇到很多关于表格的需求

下面是总结的两个项目中遇到的问题.

查看文档的话是很简单, 但是很多需求还是需要大家自己去写的.

第一个 --- 表格合并

1. 需求页面如下:

这个需求如果直接用 js 写的话就太简单了.但是使用 vue, 就需要自己修改了. 其实也不是很难,主要还是数据解析

各种合并

2. 数据结构如下:

 var list = [
        {
          "id": "16EE8A54E6917F6479905CDC5B031F22",
          "activityPointsDOS": [
            {
              "id": "16EE8A54E0C17F647404A2DC7783EE88",
              "activityPointsDOS": [
                {
                  "id": "1",
                  "value": "6",
                  "activityName": "坚定政治立场。",
                  "message": " (1)牢固树立“四个意识”巴拉巴拉",
                  "period": "19上半年"
                },
                {
                  "id": "2",
                  "value": "8",
                  "activityName": "坚定政治立场。",
                  "message": "(2)严格遵守政治纪律和政治规矩.巴拉啦",
                  "period": "19上半年"
                }
              ],
              "activityName": "1. 坚定政治立场。(10分)"
            },
            {
              "id": "16EE8A54E4817F64779EF35CC6671C10",
              "activityPointsDOS": [
                {
                  "id": "3",
                  "value": "7",
                  "activityName": "坚持学习提高。",
                  "message": "(1)及时认真参加支部集体学习....",
                  "period": "19上半年"
                },
                {
                  "id": "4",
                  "value": "3",
                  "activityName": "坚持学习提高。",
                  "message": "(2)每年集中学习培训....",
                  "period": "19上半年"
                },
                {
                  "id": "5",
                  "value": "5",
                  "activityName": "坚持学习提高。",
                  "message": "(3)有取得更高....位",
                  "period": "19上半年"
                }
              ],
              "activityName": "2.坚持学习提高。(6分)"
            },
            {
              "id": "16EE8A54E4817F64779EF35CC6671C10",
              "activityPointsDOS": [
                {
                  "id": "6",
                  "value": "7",
                  "activityName": "严格组织生活。",
                  "message": "(1)按季度.....",
                  "period": "19上半年"
                },
                {
                  "id": "7",
                  "value": "3",
                  "activityName": "严格组织生活。",
                  "message": "(2)按时上党课.......。",
                  "period": "19上半年"
                },
                {
                  "id": "8",
                  "value": "5",
                  "activityName": "坚持学习提高。",
                  "message": "(3)积极参加",
                  "period": "19上半年"
                }
              ],
              "activityName": "3.严格组织生活。(13分)"
            }
          ],
          "category": "合格积分\r\n(40分)"
        },
        {
          "id": "16EE8A54FF617F6491391BD04A0D4E7F",
          "activityPointsDOS": [
            {
              "id": "16EE8A54EA517F647D257760897C805F",
              "activityPointsDOS": [
                {
                  "id": "8",
                  "value": "10",
                  "activityName": "1.所在基层党组织情况。(10分)",
                  "message": " (1) 根据所在.....",
                  "period": "19上半年"
                }
              ],
              "activityName": "1.所在基层党组织情况。(10分)"
            },
            {
              "id": "16EE8A54E8517F647B3DE374CF0D6D93",
              "activityPointsDOS": [
                {
                  "id": "10",
                  "value": "3",
                  "activityName": "2.年度评议、考核情况。(10分)",
                  "message": " (1) 在党建....",
                  "period": "19上半年"
                },
                {
                  "id": "9",
                  "value": "10",
                  "activityName": "2.年度评议、考核情况。(10分)",
                  "message": " (2)在年度.........................................................................",
                  "period": "19上半年"
                }
              ],
              "activityName": "2.年度评议、考核情况。(10分)"
            }
          ],
          "category": "综合积分\r\n(20分)"
        }
      ];

3. 代码如下:

<el-table
        :data="alldata"
        :span-method="arraySpanMethod"
        border
        style="width: 100%">
        <el-table-column
          prop="category"
          label="项目及分值"
          width="180">
        </el-table-column>
        <el-table-column
          prop
          label="参考标准及评价方法">
          <el-table-column prop="activityName"></el-table-column>
          <el-table-column prop="message"></el-table-column>
        </el-table-column>
        <el-table-column
          prop="value"
          label="参考分值">
        </el-table-column>
      </el-table>
// 1. 获取后台数据
    created() {
      // 二次处理数据
      this.alldata = this.handleTableArr(list);
      console.log(this.alldata);
    },
 methods: {
      // 解析数据
      handleTableArr(data) {
        let arr = [];
        for (let i = 0; i < data.length; i++) {
          let category_info = data[i];
          let activityPointsDOS = category_info["activityPointsDOS"];
          let count = 0;
          for (let j = 0; j < activityPointsDOS.length; j++){
            let activityTwo_info = activityPointsDOS[j];
            let activityTwo_activityPointsDOS = activityPointsDOS[j]["activityPointsDOS"];
            for (let k = 0; k < activityTwo_activityPointsDOS.length; k++){
              count ++;
                  let info = {
                     // 确定每天数据的 合并行的数量
                      span_num: k === 0 ? activityTwo_activityPointsDOS.length : 0,
                      value:activityTwo_activityPointsDOS[k]["value"],
                      message:activityTwo_activityPointsDOS[k]["message"],
                      activityName:activityTwo_info["activityName"],
                      category: category_info["category"],
                  };
                  arr.push(info);
            }
          }
// 第一列的合并数量, 赋值给每个大项的第一个单元格. 比如合格积分要合并 8 行.
          arr[arr.length - count]["count"] = count;
        }
        return arr;
      },
    // 表格合并的方法
      arraySpanMethod({row, column, rowIndex, columnIndex}) {
        // 第一列
        if (columnIndex === 0){
          if (row.count){
            return [row.count, 1]
          }else{
            return [0, 0]
          }
        }
      // 第二列
         if (columnIndex === 1){
            if (row.span_num > 0 ){
              return [row.span_num, 1]
            }else{
              return [0, 0]
            }
          }
      }
    }

 

第二个 --- 表格纵向表头

官网上的案例都是横向的表格, 如下图:

image

而经常会遇到的需求就是纵向的表头. 数据结构不同, 写法也不一样, 各取所需.

1. 需求页面如下:

纵向

2. 数据结构如下:

补充说明: list 中的 id 是学生的日志 id, 如果 id 为 0 说明当天日志没有完成,将显示未完成, 如果有将显示可查看

loginfo: {
      'students': [
              {
                 'id':1,
                 'name':'张三',
                 'list': [
                      {'id':11},
                      {'id':0},
                      {'id':0},
                      {'id':0}]
              },
              {
                  'id':2,
                  'name':'李四',
                  'list': [
                      {'id':'21'},
                      {'id':0},
                      {'id':0},
                      {'id':0}]
              },
              {
                  'id':3,
                  'name':'王二麻子',
                  'list': [
                      {'id':0},
                      {'id':0},
                      {'id':0},
                      {'id':36}]
              }
      ],
      'dateList': ['06-01','06-02','06-03','06-04']
}

3. 代码如下:

        <el-table
            :data="loginfo.students"
            border
            style="width: 100%">
            <el-table-column
              prop="name"
              width="150"
              align="center"
              label="姓名/日期"
              fixed
            >
            </el-table-column>
            <template v-for='(col,i) in loginfo.dateList'>
              <el-table-column
                :show-overflow-tooltip="true"
                :label="col"
                :key="col"
                width="100"
                align="center"
              >
                <template slot-scope="scope">
                  <span>
                  <el-tag @click="showLog(scope.row, i)"
                          :type="scope.row.list[i].id != 0 ? 'success' : 'danger'"> {{scope.row.list[i].id != 0 ? '可查看' : '未完成'}}</el-tag>
                </span>
                </template>
              </el-table-column>
            </template>
          </el-table>

转自简书小椰子表姐G

<think>我们面临的需求是使用Element UI实现一个具有横向纵向两个表头的表格,并且数据要同时匹配这两个表头。这通常被称为“二维表头”或“多级表头”。 在Element UI中,我们可以通过嵌套`<el-table-column>`标签来实现多级表头。具体来说,我们可以在一个父级表头下嵌套子表头,从而形成横向纵向的复杂表头结构。 但是,需要注意的是,用户还要求数据能够同时匹配这两个表头。这意味着我们的数据结构需要是一个二维数组(或类似结构),其中每个单元格的数据由行列共同决定。 下面,我将逐步说明如何实现: ### 步骤1:准备数据结构 我们需要一个二维数组来表示表格的数据。同时,我们还需要两个数组分别表示横向表头纵向表头。 例如: - 纵向表头(行表头):`['属性1', '属性2', '属性3']` - 横向表头(列表头):`['指标A', '指标B', '指标C']` - 数据:一个二维数组,其中`data[i][j]`表示第i行(对应属性i)第j列(对应指标j)的值。 ### 步骤2:使用多级表头Element UI的表格中,我们可以通过嵌套`<el-table-column>`来实现多级表头。对于横向表头,我们将它们作为一级表头(父表头),然后在每个一级表头下,再嵌套纵向表头对应的列(作为二级表头)。但是,这里我们需要注意,实际上Element UI的多级表头是横向扩展的,而我们要实现的是既有横向表头(作为一级)又有纵向表头(作为二级)的二维表。 然而,更常见的做法是将纵向表头作为第一列,然后横向表头作为多级表头的第一级。具体结构如下: - 第一列:固定为纵向表头(即行表头),这一列没有子列。 - 后面的列:每个横向表头(指标)作为一级表头,然后在每个横向表头下,再为每个纵向表头(属性)设置一列?这显然不对,因为这样会导致每个横向表头下都有多个列(每个纵向属性一列),而实际上我们只需要一列(每个单元格是一个数据)。 实际上,我们这里的需求是:横向表头是多个指标(如指标A、指标B、指标C),纵向表头是多个属性(如属性1、属性2、属性3),那么整个表格应该是: | | 指标A | 指标B | 指标C | |----------|-------|-------|-------| | **属性1**| 值11 | 值12 | 值13 | | **属性2**| 值21 | 值22 | 值23 | | **属性3**| 值31 | 值32 | 值33 | 所以,我们只需要将纵向表头作为第一列(固定列),然后横向表头作为第一级表头(每个横向指标占一列)。注意,这里横向表头只有一级,纵向表头实际上并不是表头,而是作为每行的第一列(即行表头列)。 因此,我们可以这样设计: - 第一列:固定为行表头纵向),这一列使用`<el-table-column>`,并设置其`prop`为行表头对应的字段(比如我们数据中每行有一个字段表示行表头的名称,例如`rowHeader`)。 - 后面的列:每个列对应一个横向指标,我们使用`v-for`循环横向表头数组,生成多个`<el-table-column>`。 但是,如果横向表头也需要有父级(比如横向表头也分多级),那么我们就需要嵌套。而根据需求,我们只需要横向纵向两个维度,且纵向维度已经作为行表头列,所以横向表头只需要一级即可。 ### 步骤3:代码实现 假设我们的数据结构如下: ```javascript data() { return { // 纵向表头(行表头)的标签,这里我们不需要单独定义,因为行表头会作为每行的第一个字段 // 横向表头(指标) horizontalHeaders: ['指标A', '指标B', '指标C'], // 数据:数组的每个元素代表一行,每行是一个对象,包含行表头字段各个指标的值 tableData: [ { rowHeader: '属性1', indicatorA: '值11', indicatorB: '值12', indicatorC: '值13' }, { rowHeader: '属性2', indicatorA: '值21', indicatorB: '值22', indicatorC: '值23' }, { rowHeader: '属性3', indicatorA: '值31', indicatorB: '值32', indicatorC: '值33' } ] } } ``` 然后,在模板中,我们这样写: ```html <el-table :data="tableData"> <!-- 第一列:行表头纵向表头--> <el-table-column prop="rowHeader" label="属性"></el-table-column> <!-- 循环横向表头,生成指标列 --> <el-table-column v-for="header in horizontalHeaders" :key="header" :label="header"> <!-- 这里使用插槽来显示对应指标的值 --> <template slot-scope="scope"> {{ scope.row[`indicator${header.charAt(header.length-1)}`] }} <!-- 注意:上面的写法只是为了示例,实际中我们可能需要一个映射关系,将表头文本与数据字段对应 --> </template> </el-table-column> </el-table> ``` 但是,上面的写法存在一个问题:我们如何知道每个指标列对应数据中的哪个字段?在上面的数据结构中,我们使用了`indicatorA`、`indicatorB`这样的字段,但是表头数组是`['指标A','指标B','指标C']`,我们需要建立表头文本到字段名的映射。 更好的做法是,横向表头数组中的每个元素是一个对象,包含`label``prop`,其中`prop`就是该列对应的字段名。 改进后的数据结构: ```javascript data() { return { horizontalHeaders: [ { label: '指标A', prop: 'indicatorA' }, { label: '指标B', prop: 'indicatorB' }, { label: '指标C', prop: 'indicatorC' } ], tableData: [ { rowHeader: '属性1', indicatorA: '值11', indicatorB: '值12', indicatorC: '值13' }, // ... 其他行 ] } } ``` 模板: ```html <el-table :data="tableData"> <el-table-column prop="rowHeader" label="属性"></el-table-column> <el-table-column v-for="item in horizontalHeaders" :key="item.prop" :label="item.label" :prop="item.prop"> </el-table-column> </el-table> ``` 这样,我们就可以正确显示二维表了。 ### 特殊情况:如果横向表头也需要多级 如果横向表头不止一级,比如有多个父级表头,那么我们可以使用嵌套的`<el-table-column>`。例如,横向表头分为两级:第一级是“类别”,第二级是具体的指标。那么我们可以这样: ```javascript horizontalHeaders: [ { label: '类别1', children: [ { label: '指标A1', prop: 'indicatorA1' }, { label: '指标A2', prop: 'indicatorA2' } ] }, { label: '类别2', children: [ { label: '指标B1', prop: 'indicatorB1' }, { label: '指标B2', prop: 'indicatorB2' } ] } ] ``` 然后,在模板中递归或嵌套循环: ```html <el-table :data="tableData"> <el-table-column prop="rowHeader" label="属性" fixed></el-table-column> <template v-for="category in horizontalHeaders"> <el-table-column :label="category.label"> <el-table-column v-for="indicator in category.children" :key="indicator.prop" :label="indicator.label" :prop="indicator.prop"></el-table-column> </el-table-column> </template> </el-table> ``` 这样就能实现多级表头了。 ### 总结 通过以上方法,我们可以使用Element UI实现具有横向纵向表头并且数据匹配的表格。关键点在于: 1. 设计合理的数据结构,包括表头信息表格数据。 2. 使用嵌套的`<el-table-column>`来实现多级表头。 3. 注意表头与数据字段的映射关系。 ### 示例代码 下面是一个完整的示例(假设横向表头为一级): ```html <template> <el-table :data="tableData" border style="width: 100%"> <el-table-column prop="rowHeader" label="属性" width="180"></el-table-column> <el-table-column v-for="item in horizontalHeaders" :key="item.prop" :prop="item.prop" :label="item.label" width="180"> </el-table-column> </el-table> </template> <script> export default { data() { return { horizontalHeaders: [ { label: '指标A', prop: 'indicatorA' }, { label: '指标B', prop: 'indicatorB' }, { label: '指标C', prop: 'indicatorC' } ], tableData: [ { rowHeader: '属性1', indicatorA: '值11', indicatorB: '值12', indicatorC: '值13' }, { rowHeader: '属性2', indicatorA: '值21', indicatorB: '值22', indicatorC: '值23' }, { rowHeader: '属性3', indicatorA: '值31', indicatorB: '值32', indicatorC: '值33' } ] } } } </script> ``` 如果横向表头有多级,则使用嵌套循环。 §§相关问题§§ 1. 在Element UI中如何实现动态表头表头数据来自后台)? 2. 如何对二维表头表格中的数据进行排序筛选? 3. Element UI多级表头下如何实现固定列?</think># Element UI实现二维表头表格 在Element UI中实现同时具有横向纵向表头并匹配数据的表格,可以通过多级表头(`<el-table-column>`嵌套)配合特殊数据结构实现。下面是完整的解决方案: ## 实现思路 1. **数据结构设计**:使用二维数组存储表格数据,其中行对应纵向表头,列对应横向表头 2. **表头结构**: - 纵向表头作为第一列固定显示 - 横向表头通过嵌套`<el-table-column>`实现多级表头 3. **数据映射**:使用动态prop将二维数据映射到表格单元格 ## 完整实现代码 ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Element UI二维表头表格</title> <!-- 引入Element UI样式 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <style> .container { max-width: 1000px; margin: 30px auto; padding: 20px; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1); border-radius: 4px; } .header { text-align: center; margin-bottom: 30px; color: #409EFF; } .table-container { margin: 20px 0; } .note { background-color: #f8f8f8; padding: 15px; border-radius: 4px; margin-top: 20px; font-size: 14px; } .note-title { font-weight: bold; margin-bottom: 8px; color: #67C23A; } </style> </head> <body> <div id="app"> <div class="container"> <h1 class="header">二维表头表格实现</h1> <div class="table-container"> <el-table :data="tableData" border style="width: 100%" :header-cell-style="{background: '#f5f7fa', fontWeight: 'bold'}" height="500"> <!-- 纵向表头--> <el-table-column prop="verticalHeader" label="产品/季度" fixed="left" width="150" align="center"> </el-table-column> <!-- 横向表头 - 嵌套多级表头 --> <el-table-column v-for="(year, yearIndex) in horizontalHeaders" :key="yearIndex" :label="year.label" align="center"> <el-table-column v-for="(quarter, quarterIndex) in year.children" :key="quarterIndex" :label="quarter.label" :prop="`cell_${yearIndex}_${quarterIndex}`" align="center" width="120"> </el-table-column> </el-table-column> </el-table> </div> <div class="note"> <div class="note-title">实现说明:</div> <p>1. 纵向表头(产品名称)作为第一列固定显示</p> <p>2. 横向表头使用嵌套结构:年度 → 季度</p> <p>3. 动态prop格式:<code>cell_${yearIndex}_${quarterIndex}</code></p> <p>4. 数据结构为对象数组,每行包含纵向表头横向数据</p> </div> </div> </div> <!-- 引入VueElement UI --> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <script> new Vue({ el: '#app', data() { return { // 横向表头配置 horizontalHeaders: [ { label: '2023年', children: [ { label: 'Q1', prop: 'cell_0_0' }, { label: 'Q2', prop: 'cell_0_1' }, { label: 'Q3', prop: 'cell_0_2' }, { label: 'Q4', prop: 'cell_0_3' } ] }, { label: '2024年', children: [ { label: 'Q1', prop: 'cell_1_0' }, { label: 'Q2', prop: 'cell_1_1' }, { label: 'Q3', prop: 'cell_1_2' }, { label: 'Q4', prop: 'cell_1_3' } ] } ], // 表格数据 tableData: [ { verticalHeader: '智能手机', cell_0_0: '¥1,250万', cell_0_1: '¥1,380万', cell_0_2: '¥1,520万', cell_0_3: '¥1,650万', cell_1_0: '¥1,420万', cell_1_1: '¥1,580万', cell_1_2: '¥1,720万', cell_1_3: '¥1,850万' }, { verticalHeader: '笔记本电脑', cell_0_0: '¥890万', cell_0_1: '¥920万', cell_0_2: '¥850万', cell_0_3: '¥980万', cell_1_0: '¥1,050万', cell_1_1: '¥1,120万', cell_1_2: '¥1,080万', cell_1_3: '¥1,150万' }, { verticalHeader: '智能手表', cell_0_0: '¥320万', cell_0_1: '¥380万', cell_0_2: '¥420万', cell_0_3: '¥480万', cell_1_0: '¥520万', cell_1_1: '¥580万', cell_1_2: '¥620万', cell_1_3: '¥680万' }, { verticalHeader: '平板电脑', cell_0_0: '¥580万', cell_0_1: '¥620万', cell_0_2: '¥550万', cell_0_3: '¥590万', cell_1_0: '¥630万', cell_1_1: '¥670万', cell_1_2: '¥720万', cell_1_3: '¥780万' }, { verticalHeader: '耳机', cell_0_0: '¥210万', cell_0_1: '¥230万', cell_0_2: '¥250万', cell_0_3: '¥280万', cell_1_0: '¥310万', cell_1_1: '¥330万', cell_1_2: '¥350万', cell_1_3: '¥380万' } ] }; } }); </script> </body> </html> ``` ## 关键实现点说明 1. **表头结构**: - 纵向表头作为固定列显示在左侧 - 横向表头使用嵌套的`<el-table-column>`实现年份→季度的多级结构 2. **数据映射**: ```javascript // 数据对象结构示例 { verticalHeader: '产品名称', cell_0_0: '2023年Q1数据', cell_0_1: '2023年Q2数据', // ... cell_1_3: '2024年Q4数据' } ``` 3. **动态prop绑定**: ```html <el-table-column v-for="(quarter, quarterIndex) in year.children" :prop="`cell_${yearIndex}_${quarterIndex}`"> </el-table-column> ``` ## 实际应用场景 这种二维表头表格适用于: 1. 销售数据报表(产品 vs 时间段) 2. 绩效考核表(员工 vs 考核指标) 3. 实验数据记录(样本 vs 测试条件) 4. 财务对比分析(项目 vs 会计期间) ## 相关问题 1. **如何动态生成二维表头结构?** 可以通过API获取表头配置,使用`v-for`动态渲染表头结构,同时动态生成对应的数据字段。 2. **如何实现表头固定滚动?** 使用Element UI的`fixed`属性固定纵向表头列,设置`height`属性启用表格滚动条,确保大数据量下的可用性。 3. **如何优化大型二维表格的性能?** 可以采用虚拟滚动技术,只渲染可视区域内的单元格,或者对数据进行分页/懒加载处理。 4. **如何添加单元格编辑功能?** 可以使用`<template slot-scope>`自定义单元格内容,结合Element UI的输入组件实现编辑功能。 5. **如何导出二维表头表格数据?** 可以使用第三方库如SheetJS或xlsx,将表头结构表格数据转换为Excel格式导出。 6. **如何实现表头合并?** 对于更复杂的表头结构,可以通过设置`<el-table-column>`的`colspan``rowspan`属性实现表头单元格合并。 通过这种实现方式,可以创建功能完整、结构清晰的二维表头表格,满足复杂数据展示需求[^1][^2]。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值