iview table 行列合并
valten Lv4

1. 需求

后台获取的数据,前端渲染时,如果同一列相邻的数据相同,则合并成一个单元格。

2 官方示例

设置属性 span-method 可以指定合并行或列的算法。

该方法参数为 4 个对象:

  • row: 当前行
  • column: 当前列
  • rowIndex: 当前行索引
  • columnIndex: 当前列索引

该函数可以返回一个包含两个元素的数组,第一个元素代表 rowspan,第二个元素代表 colspan。 也可以返回一个键名为 rowspan 和 colspan 的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<template>
<Table :columns="columns" :data="data" border :span-method="handleSpan"></Table>
</template>
<script>
export default {
data () {
return {
columns: [
{
title: 'Date',
key: 'date'
},
{
title: 'Name',
key: 'name'
},
{
title: 'Age',
key: 'age'
},
{
title: 'Address',
key: 'address'
}
],
data: [
{
name: 'John Brown',
age: 18,
address: 'New York No. 1 Lake Park',
date: '2016-10-03'
},
{
name: 'Jim Green',
age: 24,
address: 'London No. 1 Lake Park',
date: '2016-10-01'
},
{
name: 'Joe Black',
age: 30,
address: 'Sydney No. 1 Lake Park',
date: '2016-10-02'
},
{
name: 'Jon Snow',
age: 26,
address: 'Ottawa No. 2 Lake Park',
date: '2016-10-04'
}
]
}
},
methods: {
handleSpan ({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0 && columnIndex === 0) {
return [1, 2];
} else if (rowIndex === 0 && columnIndex === 1) {
return [0, 0];
}
if (rowIndex === 2 && columnIndex === 0) {
return {
rowspan: 2,
colspan: 1
};
} else if (rowIndex === 3 && columnIndex === 0) {
return {
rowspan: 0,
colspan: 0
};
}
}
}
}
</script>

注意:合并和被合并的区别,返回值不是[0,0]的,其内容显示在合并后的单元格中。返回值是[0,0]的是被合并的单元格,内容相当于删除

效果图

3 动态合并

handleSpan 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* 合并行或列的算法
* @param row 当前行
* @param column 当前列
* @param rowIndex 当前行索引
* @param columnIndex 当前列索引
* @returns {{colspan: (number), rowspan: *}}
*/
handleSpan({ row, column, rowIndex, columnIndex }) {
// 姓名合并
if (columnIndex === 0) {
// 二维数组存储的数据 取出
const _row = this.nameMerges[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}

// 地址合并
if (columnIndex === 2) {
// 二维数组存储的数据 取出
const _row = this.addrMerges[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}

if (columnIndex === 4) {
// 操作列序号
// 二维数组存储的数据 取出
const _row = this.opMerges[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},

处理数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
formatData() {
this.nameMerges = this.getMerges(this.resData, "name");
this.addrMerges = this.getMerges(this.resData, "address");
this.opMerges = [...this.nameMerges]; // 复制name的合并信息

console.log(this.opMerges);
},
/**
*
* @param data 数据列表
* @param key 将要合并的对比字段
* @returns {*[]}
*/
getMerges(data, key) {

let spanArr = []
let pos = 0
// 遍历数据
data.forEach((item, index) => {
// 判断是否是第一项
if (index === 0) {
spanArr.push(1)
pos = 0
} else {
// 不是第一项时,就根据标识去存储
if (data[index][key] === data[index - 1][key]) {
// 查找到符合条件的数据时每次要把之前存储的数据+1
spanArr[pos] += 1
spanArr.push(0)
} else {
// 没有符合的数据时,要记住当前的index
spanArr.push(1)
pos = index
}
}
})
return spanArr
},

从后台拿到数据后,先调用下处理数据的方法

1
this.formatData();

完整代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<template>
<Table
class="border-table"
:columns="columns"
:data="resData"
border
:span-method="handleSpan"
>
<!-- 操作 -->
<template slot="xm" slot-scope="{ row, index }">
<a href="">{{ row.name }}</a>
</template>
<!-- 操作 -->
<template slot="action" slot-scope="{ row, index }">
<div class="tableBtnBox enniu">
<div class="tableBtn">
<Button class="cz_btn" type="success" size="small">查看详情</Button>
</div>
</div>
</template>
</Table>
</template>
<script>
export default {
data() {
return {
columns: [
{
title: "Name",
// key: "name",
slot: "xm",
},
{
title: "Age",
key: "age",
},
{
title: "Address",
key: "address",
},
{
title: "Desc",
key: "desc",
},
{
title: "操作",
align: "center",
slot: "action",
},
],
resData: [
{
"id": 1,
"name": "John Doe",
"age": 32,
"address": "202 Main Street, New York, NY",
"desc": "Data engineer"
},
{
"id": 2,
"name": "Lisa Wang",
"age": 28,
"address": "99 Long Road, Shanghai, CN",
"desc": "Product manager"
},
{
"id": 3,
"name": "Jane Smith",
"age": 35,
"address": "99 Long Road, Shanghai, CN",
"desc": "Software architect"
},
{
"id": 4,
"name": "Jane Smith",
"age": 29,
"address": "51 South Avenue, Miami, FL",
"desc": "UI designer"
},
{
"id": 5,
"name": "Tom Brown",
"age": 29,
"address": "1675 Park Avenue, Paris, FR",
"desc": "Backend developer"
},
{
"id": 6,
"name": "Alice Chen",
"age": 30,
"address": "20 Surry Street, London, UK",
"desc": "DevOps engineer"
}
],
nameMerges: [],
addrMerges: [],
opMerges: [],
};
},
methods: {
/**
* 合并行或列的算法
* @param row 当前行
* @param column 当前列
* @param rowIndex 当前行索引
* @param columnIndex 当前列索引
* @returns {{colspan: (number), rowspan: *}}
*/
handleSpan({ row, column, rowIndex, columnIndex }) {
// 姓名合并
if (columnIndex === 0) {
// 二维数组存储的数据 取出
const _row = this.nameMerges[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}

// 地址合并
if (columnIndex === 2) {
// 二维数组存储的数据 取出
const _row = this.addrMerges[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}

if (columnIndex === 4) {
// 操作列序号
// 二维数组存储的数据 取出
const _row = this.opMerges[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
},
formatData() {
this.nameMerges = this.getMerges(this.resData, "name");
this.addrMerges = this.getMerges(this.resData, "address");
this.opMerges = [...this.nameMerges]; // 复制name的合并信息

console.log(this.opMerges);
},
/**
*
* @param data 数据列表
* @param key 将要合并的对比字段
* @returns {*[]}
*/
getMerges(data, key) {
// 页面展示的数据,不一定是全部的数据,所以每次都清空之前存储的 保证遍历的数据是最新的数据。以免造成数据渲染混乱
let spanArr = [];
let pos = 0;
// 遍历数据
data.forEach((item, index) => {
// 判断是否是第一项
if (index === 0) {
spanArr.push(1);
pos = 0;
} else {
// 不是第一项时,就根据标识去存储
if (data[index][key] === data[index - 1][key]) {
// 查找到符合条件的数据时每次要把之前存储的数据+1
spanArr[pos] += 1;
spanArr.push(0);
} else {
// 没有符合的数据时,要记住当前的index
spanArr.push(1);
pos = index;
}
}
});
return spanArr;
},
},
mounted() {
this.formatData();
},
};
</script>
<style scoped>

</style>

效果图

  • 本文标题:iview table 行列合并
  • 本文作者:valten
  • 创建时间:2023-07-27 15:04:39
  • 本文链接:https://valtenhyl.github.io/技术教程/iview-table-merge/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论