vue3 + antd-vue@4 a-table单元格合并,rowSpan(行合并),colSpan(列合并)详解, 表头合并详解, 表头自定义详解

12 篇文章 1 订阅
6 篇文章 1 订阅

一、解释

        1、rowSpan

                1)、行合并

                2)、当为0时:去掉边框

                3)、当为1时:不合并

                4)、大于1的x时:包含当前单元格行合并x个单元格

        2、colSpan

                1)、列合并

                2)、当为0时:去掉边框

                3)、当为1时:不合并

                4)、大于1的x时:包含当前单元格列合并x个单元格

二、代码实现核心代码位置

在table对应的列的 customCell 返回对应需要合并的参数

const state = reactive({
  columns: [
    {
      title: 'VLAN值',
      dataIndex: 'value',
      key: 'value',
      align: 'center',
      colSpan: 2, // 表头合并
      width: '120px',

      // 合并单元格配置
      customCell: (_, index) => {
        // _:当前行的数据, index:当前行的索引
        return {
          rowSpan:x,
          colSpan:y
        };
      }
    },
    {
      title: 'VLAN平面',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
      colSpan: 0, // 前面一个字段合并2个, 因此紧接着的这个字段这里需要设置成0
      width: '120px',

      // 合并单元格配置
      customCell: (_, index) => {
      // _:当前行的数据, index:当前行的索引
        return {
          rowSpan:x,
          colSpan:y
        };
      }
    },
    ...
    ]
})

三、表格合并举例说明

1、初始效果

        

2、代码

        1)、完整代码里包行自定义表头的方法
<template>
  <div class="container-warp">
    <div class="content">
      <a-table
        class="ant-table-striped"
        bordered
        :dataSource="state.tableSource"
        :columns="state.columns"
        :pagination="pagination"
        :scroll="{ x: state.tableWidth }"
        :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)">
        <!-- 表头自定义 -->
        <template #headerCell="{ column }">
          <template v-if="column.dataIndex === 'deviceAttr1'">
            <div class="result-warp">
              <span>配置结果</span>
              <a-button :loading="state.resultLoading" type="link">
                <template #icon>
                  <SearchOutlined />
                </template>
              </a-button>
            </div>
          </template>
        </template>
        <!-- 表格标题自定义 -->
        <template #title="{ column }">
          <div style="text-align: center">!红色背景代表配置校验未通过,黄色背景代表配置校验需要二次确认</div>
        </template>
        <!-- 表格单元格自定义 -->
        <template #bodyCell="{ column, text, record, index }">
          <template v-if="column.dataIndex == 'status'">{{ statusEnum[text] }}</template>
          <template v-if="column.dataIndex == 'deviceAttr1'">
            <div
              style="padding: 5px 10px"
              :class="text == '未配置' ? 'result-un-config' : 'result-config'"
              :style="{ backgroundColor: text == '未配置' ? '#f00' : '#ff0', color: text == '未配置' ? '#fff' : '#000' }">
              {{ text }}
            </div>
          </template>
        </template>
      </a-table>
    </div>
  </div>
</template>

<script setup>
import { getTableWidth } from '@/utils/index.utils.js';
import { reactive } from 'vue';

const state = reactive({
  columns: [
    {
      title: 'VLAN值',
      dataIndex: 'value',
      key: 'value',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {};
      }
    },
    {
      title: 'VLAN平面',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {};
      }
    },
    { title: '设备名称', dataIndex: 'deviceName', key: 'deviceName', align: 'center', width: '200px' },
    { title: '设备属性1', dataIndex: 'deviceAttr1', key: 'deviceAttr1', align: 'center', width: '200px' },
    { title: '设备属性2', dataIndex: 'deviceAttr2', key: 'deviceAttr2', align: 'center', width: '200px' },
    { title: '设备属性3', dataIndex: 'deviceAttr3', key: 'deviceAttr3', align: 'center', width: '200px' },
    { title: '设备属性4', dataIndex: 'deviceAttr4', key: 'deviceAttr4', align: 'center', width: '200px' },
    { title: '设备属性5', dataIndex: 'deviceAttr5', key: 'deviceAttr5', align: 'center', width: '200px' },
    { title: '设备属性6', dataIndex: 'deviceAttr6', key: 'deviceAttr6', align: 'center', width: '200px' },
    {
      title: '确认状态',
      dataIndex: 'confirm',
      key: 'confirm',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {};
      }
    }
  ],
  tableSource: [
    {
      value: '100',
      type: 'vlan',
      deviceName: '设备100-1',
      deviceAttr1: '已配置',
      deviceAttr2: '是',
      deviceAttr3: '是',
      deviceAttr4: '是',
      deviceAttr5: '是',
      deviceAttr6: '是',
      confirm: '已确认'
    },
    {
      value: '100',
      type: 'vlan',
      deviceName: '设备100-2',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '已确认'
    },
    {
      value: '101',
      type: 'vlan',
      deviceName: '设备101',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认'
    },
    {
      value: '102',
      type: 'vlan',
      deviceName: '设备102-1',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认'
    },
    {
      value: '102',
      type: 'vlan',
      deviceName: '设备102-2',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认'
    },
    {
      value: '102',
      type: 'vlan',
      deviceName: '设备102-3',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认'
    }
  ],
  tableWidth: 1200
});
state.tableWidth = getTableWidth(state.columns);
</script>

<style lang="less" scoped>
.container-warp {
  width: 100%;
  height: 100%;
  background-color: #f5f5f5;
  padding: 20px;
  .content {
    padding: 20px;
    background-color: #fff;
  }
}
</style>

 2、eg1:

如图, 假如需要合并 框出的两个单元格(列合并)

这个时候就需要使用列合并colSpan,将第1行的第一个字段与第2个字段就行,代码如下

 columns: [
    {
      title: 'VLAN值',
      dataIndex: 'value',
      key: 'value',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          colSpan: index === 0 ? 2 : 1 // 第一个字段的第一行列合并 2
        };
      }
    },
    {
      title: 'VLAN平面',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          colSpan: index === 0 ? 0 : 1 // 第一个字段的第一行列合并 0, 去掉原有单元个
        };
      }
    },
    ...
]

特别注意:

        如果合并2个, 第一个设置colSpan:2, 第一个后面紧接着的 1 个字段必须设置colSpan:0, 行合并也同理

        如果合并5个, 第一个设置colSpan:5, 第一个后面紧接着的 4 个字段必须设置colSpan:0, 行合并也同理

如果后面的不设置span:0就会出现一下结果:单元个往后推移了一个

3、eg2:

如图, 假如需要合并 框出的三个单元格(行合并)

这个时候就需要使用列合并rowSpan,将第1个字段的第一行到第3行合并,代码如下

const state = reactive({
  columns: [
    {
      title: 'VLAN值',
      dataIndex: 'value',
      key: 'value',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          rowSpan: index === 0 ? 3 : 1
        };
      }
    },
    {
      title: 'VLAN平面',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          rowSpan: index === 1 || index === 2 ? 0 : 1
        };
      }
    },
    ...
  ]
})

效果如下

特别注意:

        如果合并3行, 第一个设置rowSpan:2, 第一个后面紧接着的 2 行必须设置colSpan:0, 行合并也同理

        如果合并5个, 第一个设置rowSpan:5, 第一个后面紧接着的 4 行必须设置colSpan:0, 行合并也同理

4、eg3:

如图, 以valn值 为基础,由于vlan值重复, 需要合并如下图框处的单元格 (中间部分为设备信息, 一个vlan里出现了多台设备的情况)

根据需求, 就应该需要就可以得到,字段 vlan值、vlan平面、确认状态三个字段(三列)的第1行第2行需要合并在一起, 第4行-第6行需要合并,(所以就需要从这三个字段的 customCell 入手) 实现代码如下,(因为只是行合并就只需要操作rowSpan即可)

const state = reactive({
  columns: [
    {
      title: 'VLAN值',
      dataIndex: 'value',
      key: 'value',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          rowSpan: _.rowSpan
        };
      }
    },
    {
      title: 'VLAN平面',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          rowSpan: _.rowSpan
        };
      }
    },
    ...
    {
      title: '确认状态',
      dataIndex: 'confirm',
      key: 'confirm',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        return {
          rowSpan: _.rowSpan
        };
      }
    }
  ],
  tableSource: [
    {
      value: '100',
      type: 'vlan',
      deviceName: '设备100-1',
      deviceAttr1: '已配置',
      deviceAttr2: '是',
      deviceAttr3: '是',
      deviceAttr4: '是',
      deviceAttr5: '是',
      deviceAttr6: '是',
      confirm: '已确认',
      rowSpan: 2  // 第1行 行合并2个单元个
    },
    {
      value: '100',
      type: 'vlan',
      deviceName: '设备100-2',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '已确认',
      rowSpan: 0  // 由于 第1行 行合并2个占用了此行,因此需要设置rowSpan: 0去掉此行
    },
    {
      // 第3行不合并不做处理 加上rowSpan:1也没有关系
      value: '101',
      type: 'vlan',
      deviceName: '设备101',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认'
    },
    {
      value: '102',
      type: 'vlan',
      deviceName: '设备102-1',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认',
      rowSpan: 3  // 第4行 行合并3个单元个, 因为行合并3后面的2行都要 rowSpan都要设置成0
    },
    {
      value: '102',
      type: 'vlan',
      deviceName: '设备102-2',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认',
      rowSpan: 0 // 由于 第4行 行合并2个占用了此行,因此需要设置rowSpan: 0去掉此行
    },
    {
      value: '102',
      type: 'vlan',
      deviceName: '设备102-3',
      deviceAttr1: '未配置',
      deviceAttr2: '否',
      deviceAttr3: '否',
      deviceAttr4: '否',
      deviceAttr5: '否',
      deviceAttr6: '否',
      confirm: '待确认',
      rowSpan: 0 // 由于 第4行 行合并2个占用了此行,因此需要设置rowSpan: 0去掉此行
    }
  ],
  tableWidth: 1200
});

一下代码与上面代码等同


  columns: [
    {
      title: 'VLAN值',
      dataIndex: 'value',
      key: 'value',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        let spanEmun = {
          0: 2,
          1: 0,
          2: 1,
          3: 3,
          4: 0,
          5: 0
        };
        return {
          rowSpan: spanEmun[index]
        };
      }
    },
    {
      title: 'VLAN平面',
      dataIndex: 'type',
      key: 'type',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        let spanEmun = {
          0: 2,
          1: 0,
          2: 1,
          3: 3,
          4: 0,
          5: 0
        };
        return {
          rowSpan: spanEmun[index]
        };
      }
    },
    { title: '设备名称', dataIndex: 'deviceName', key: 'deviceName', align: 'center', width: '200px' },
    { title: '设备属性1', dataIndex: 'deviceAttr1', key: 'deviceAttr1', align: 'center', width: '200px' },
    { title: '设备属性2', dataIndex: 'deviceAttr2', key: 'deviceAttr2', align: 'center', width: '200px' },
    { title: '设备属性3', dataIndex: 'deviceAttr3', key: 'deviceAttr3', align: 'center', width: '200px' },
    { title: '设备属性4', dataIndex: 'deviceAttr4', key: 'deviceAttr4', align: 'center', width: '200px' },
    { title: '设备属性5', dataIndex: 'deviceAttr5', key: 'deviceAttr5', align: 'center', width: '200px' },
    { title: '设备属性6', dataIndex: 'deviceAttr6', key: 'deviceAttr6', align: 'center', width: '200px' },
    {
      title: '确认状态',
      dataIndex: 'confirm',
      key: 'confirm',
      align: 'center',
      width: '120px',
      customCell: (_, index) => {
        let spanEmun = {
          0: 2,
          1: 0,
          2: 1,
          3: 3,
          4: 0,
          5: 0
        };
        return {
          rowSpan: spanEmun[index]
        };
      }
    }
  ],

效果如下:

5、eg4:

自己项目遇到的合并信息

解释一下, 其实后端给的数据时这样的, 两个vlan信息,每个vlan信息下面都有自己的设备列表, 因此需要我们自己把设备列表提出来,实现满足table的格式,

这个时候就需要处理数据

结果如下

四、表头合并

        只需要在 columns 中设置 colSpan 即可, 跟表格原理一样

        eg:

                如图需要合并框出来的表头

       

        代码如下:
const state = reactive({
  columns: [
    ...
    { title: '设备属性集', dataIndex: 'deviceAttr2', key: 'deviceAttr2', colSpan: 5, align: 'center', width: '200px' },
    { title: '设备属性3', dataIndex: 'deviceAttr3', key: 'deviceAttr3', colSpan: 0, align: 'center', width: '200px' },
    { title: '设备属性4', dataIndex: 'deviceAttr4', key: 'deviceAttr4', colSpan: 0, align: 'center', width: '200px' },
    { title: '设备属性5', dataIndex: 'deviceAttr5', key: 'deviceAttr5', colSpan: 0, align: 'center', width: '200px' },
    { title: '设备属性6', dataIndex: 'deviceAttr6', key: 'deviceAttr6', colSpan: 0, align: 'center', width: '200px' },
    ...
  ],
})
        效果如下:

        特别注意:从合并开始, 后面的字段都要设置成colSpan:0, 和单元个合并同理

​​​​​​​

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
您可以通过自定义合并规则来实现vue element-ui table单元格的动态合并。以下是一个简单的示例代码: ``` <template> <el-table :data="tableData" ref="multiTable" border> <el-table-column prop="name" label="Name" width="180"> </el-table-column> <el-table-column prop="age" label="Age" width="180"> </el-table-column> <el-table-column prop="gender" label="Gender" width="180" :cell-style="{padding: '0px'}" :render-header="renderHeader" :render-cell="renderCell"> </el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { name: 'Tom', age: 18, gender: 'M' }, { name: 'Jane', age: 22, gender: 'F' }, { name: 'John', age: 28, gender: 'M' }, { name: 'Lisa', age: 24, gender: 'F' } ] } }, methods: { // 自定义表头渲染函数 renderHeader(h, { column }) { if (column.property === 'gender') { return h('div', [ h('span', 'Gender'), h('el-checkbox', { on: { change: this.handleMultiHeaderChange } }) ]) } else { return h('div', column.label) } }, // 自定义单元格渲染函数 renderCell(h, { row, column }, index) { const rowspan = this.getMultiRowspan(row, column) if (rowspan === 0) { return '' } else { return h('div', { style: { lineHeight: `${80 * rowspan}px` }, attrs: { rowspan: rowspan } }, row.gender) } }, // 计算单元格数 getMultiRowspan(row, column) { const data = this.tableData let rowspan = 1 let currentIndex = data.indexOf(row) for (let i = currentIndex + 1; i < data.length; i++) { if (data[i][column.property] === row[column.property]) { rowspan++ } else { break } } return rowspan }, // 表头复选框改变事件 handleMultiHeaderChange(value) { const table = this.$refs.multiTable const columns = table.columns columns.forEach((column) => { if (column.property === 'gender') { column.filteredValue = value ? ['M', 'F'] : [] table.store.commit('filterChange', { column: column }) } }) } } } </script> ``` 在这个示例代码中,我们使用了自定义渲染函数来渲染表格,其中: - `renderHeader` 函数用于渲染表头,其中包含一个复选框来控制表格的动态合并; - `renderCell` 函数用于渲染单元格,其中通过 `getMultiRowspan` 函数计算出单元格需要跨越的数。 需要注意的是,这里的示例代码仅供参考,具体实现可能会因为表格数据结构和合并规则的不同而有所不同。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snows_l

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值