最近开发任务的需求,合并行,话不多说先上需求
需要将第一行拉通,第三列通过分组设置合并行,简单了解下文档。
设置属性 span-method 可以指定合并行或列的算法,该方法参数为 4 个对象:
- row: 当前行
- column: 当前列
- rowIndex: 当前行索引
- columnIndex: 当前列索引 该函数可以返回一个包含两个元素的数组,第一个元素代表 rowspan,第二个元素代表 colspan。 也可以返回一个键名为 rowspan 和 colspan 的对象。这是一个官网描述
处理第一行合并拉通
/** 行合并 */
handleSpan({ row, column, rowIndex, columnIndex }) {
// 第一列所有行合并
if (rowIndex === 0 && columnIndex === 0) {
return {
rowspan: this.dataSource.length,
colspan: 1
}
} else if (rowIndex !== 0 && columnIndex === 0) {
return {
rowspan: 0,
colspan: 0
}
}
}
通过判断行索引和列索引 逗是否为0 如果是 ,则合并rowspan,否则就隐藏。第一个合并的解决了,看下效果
开始处理第三列数据行
怎么合并呢,怎么确定合并多少行?先看看我的方式 咋样
- 通过关键字遍历每条数据进行分组
- 统计该关键字出现的次数
- 再次循环数据,通过key值,将统计的行数赋值给第一次出现的对象,并删除统计的行数
/** 处理数据 */
handleDataSource() {
const obj = {} // 记录 合并行 行数
const GROUP_FIELD = 'group'
// 记录需要合并的行数
this.dataSource.forEach((item) => {
if (!obj[item[GROUP_FIELD]]) {
obj[item[GROUP_FIELD]] = 1
} else {
obj[item[GROUP_FIELD]] += 1
}
})
// 将合并的第二列通过 rowSpanCounter来记录,如果有值 则分组,如果没值,则在分组内
this.dataSource = this.dataSource.map((item) => {
if (obj[item[GROUP_FIELD]]) {
item.rowSpanCounter = obj[item[GROUP_FIELD]]
delete obj[item[GROUP_FIELD]]
}
return item
})
}
注意观察格式,只有合并的行才会出现rowSpanCounter,那么在合并行处理的时候就直接判断行是否有这个属性就行了
// 第二列通过分组来合并
if (columnIndex === 2) {
// 如果行存在rowSpanCounter,则通过这个字段来合并行
if (row.rowSpanCounter) {
return {
rowspan: row.rowSpanCounter,
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
实现效果:
ok,是否所有都解决了呢,贴个完整代码,有需要的自取,当然有更好的处理方式,欢迎讨论
<template>
<Drawer :title="$t('HPC专属资源池-价格详情')" width="700" v-model="visible">
<h4>
<span>{{ $t('计算资源') }}</span>
</h4>
<Table :columns="columns" :data="dataSource" border :span-method="handleSpan"></Table>
</Drawer>
</template>
<script>
export default {
data() {
this.rules = {}
this.columns = [
{ title: this.$t('资源类型'), key: 'resourceType', ellipsis: true, width: 100 },
{ title: this.$t('规格分组'), key: 'specGroup', ellipsis: true, width: 100 },
{ title: this.$t('计费规格'), key: 'chargeSped', ellipsis: true, width: 100 },
{
title: this.$t('价格'),
key: 'price'
}
]
return {
visible: true,
loading: false,
dataSource: []
}
},
created() {
this.dataSource = [
{
resourceType: '计算',
group: 'test',
specGroup: 'test(HA)',
chargeSped: 'paired',
price: '按量计费:¥0.00000/小时'
},
{
resourceType: '计算',
group: 'test',
specGroup: 'test(HA)',
chargeSped: 'paired',
price: '包年包月:¥10.00/月'
},
{
resourceType: '计算',
group: 'test1',
specGroup: 'test(非HA)',
chargeSped: 'paired',
price: '按量计费:¥0.00000/小时'
},
{
resourceType: '计算',
group: 'test1',
specGroup: 'test(非HA)',
chargeSped: 'paired',
price: '包年包月:¥10.00/月'
},
{
resourceType: '计算',
group: 'test3',
specGroup: 'test(HA)',
chargeSped: 'paired',
price: '按量计费:¥0.00000/小时'
},
{
resourceType: '计算',
group: 'test3',
specGroup: 'test(HA)',
chargeSped: 'paired',
price: '包年包月:¥10.00/月'
},
{
resourceType: '计算',
group: 'test4',
specGroup: 'test(HA)',
chargeSped: 'paired',
price: '按量计费:¥0.00000/小时'
},
{
resourceType: '计算',
group: 'test4',
specGroup: 'test(HA)',
chargeSped: 'paired',
price: '包年包月:¥10.00/月'
}
]
this.handleDataSource()
},
methods: {
/** 处理数据 */
handleDataSource() {
const obj = {} // 记录 合并行 行数
const GROUP_FIELD = 'group'
// 记录需要合并的行数
this.dataSource.forEach((item) => {
if (!obj[item[GROUP_FIELD]]) {
obj[item[GROUP_FIELD]] = 1
} else {
obj[item[GROUP_FIELD]] += 1
}
})
// 将合并的第二列通过 rowSpanCounter来记录,如果有值 则分组,如果没值,则在分组内
this.dataSource = this.dataSource.map((item) => {
if (obj[item[GROUP_FIELD]]) {
item.rowSpanCounter = obj[item[GROUP_FIELD]]
delete obj[item[GROUP_FIELD]]
}
return item
})
},
openModal(id) {
this.visible = true
},
/** 行合并 */
handleSpan({ row, column, rowIndex, columnIndex }) {
// 第一列所有行合并
if (rowIndex === 0 && columnIndex === 0) {
return {
rowspan: this.dataSource.length,
colspan: 1
}
} else if (rowIndex !== 0 && columnIndex === 0) {
return {
rowspan: 0,
colspan: 0
}
}
// 第二列通过分组来合并
if (columnIndex === 2) {
// 如果行存在rowSpanCounter,则通过这个字段来合并行
if (row.rowSpanCounter) {
return {
rowspan: row.rowSpanCounter,
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
}
}
}
</script>
<style lang="less" scoped>
h4 {
background: #f5f6f7;
line-height: 35px;
padding: 0 15px;
margin: 0 0 15px 0;
}
</style>