[TOC]
>[success] # Element UI table合并行(上下行)
通过给`table`传入`span-method`方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行`row`、当前列`column`、当前行号`rowIndex`、当前列号`columnIndex`四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表`rowspan`,第二个元素代表`colspan`。 也可以返回一个键名为`rowspan`和`colspan`的对象。
>[success] ## 官方案例
如图,上面的表格时合并列,下面的表格是合并行
![](https://img.kancloud.cn/60/1d/601ded7a48b8f00262df3f058aef2021_1067x700.png)
html
~~~
<template>
<div>
<!-- 合并列 -->
<el-table :data="tableData" :span-method="arraySpanMethod" border style="width: 100%">
<el-table-column prop="id" label="ID" width="180"/>
<el-table-column prop="name" label="姓名"/>
<el-table-column prop="amount1" sortable label="数值 1"/>
<el-table-column prop="amount2" sortable label="数值 2"/>
<el-table-column prop="amount3" sortable label="数值 3"/>
</el-table>
<br>
<br>
<br>
<br>
<!-- 合并行 -->
<el-table :data="tableData" :span-method="objectSpanMethod" border style="width: 100%; margin-top: 20px">
<el-table-column prop="id" label="ID" width="180"/>
<el-table-column prop="name" label="姓名"/>
<el-table-column prop="amount1" label="数值 1(元)"/>
<el-table-column prop="amount2" label="数值 2(元)"/>
<el-table-column prop="amount3" label="数值 3(元)"/>
</el-table>
</div>
</template>
~~~
Javascript
~~~
<script>
export default{
data() {
return {
tableData: [
{
id: '12987122',
name: '王小虎',
amount1: '234',
amount2: '3.2',
amount3: 10
},
{
id: '12987123',
name: '王小虎',
amount1: '165',
amount2: '4.43',
amount3: 12
},
{
id: '12987124',
name: '王小虎',
amount1: '324',
amount2: '1.9',
amount3: 9
},
{
id: '12987125',
name: '王小虎',
amount1: '621',
amount2: '2.2',
amount3: 17
},
{
id: '12987126',
name: '王小虎',
amount1: '539',
amount2: '4.1',
amount3: 15
}
]
}
},
methods: {
// 合并列方法
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
if (rowIndex % 2 === 0) { // 行索引为偶数时
if (columnIndex === 0) { // 列索引为 第1列时
return [1, 2] // [行跨度,列跨度 ]
} else if (columnIndex === 1) {
return [0, 0] // [行跨度,列跨度 ]
}
}
},
// 合并行的计算方法
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) { // 用于设置要合并的列 这里是指第一列合并
if (rowIndex % 2 === 0) { // 用于设置合并开始的行号,具体结合下方案例理解
return {
rowspan: 2, // 要合并的行数
colspan: 1 // 要合并的列数
};
} else {
return {
rowspan: 0, // 要合并的行数,为 0 则直接不显示
colspan: 0 // 要合并的列数,为 0 则直接不显示
};
}
}
}
}
}
</script>
~~~
<br/>
>[success] ## 每列按照同一种规则合并行(上下行)
假如我想写下面这样的表格,第1、2、3和最后一列的合并方式都一样。
![](https://img.kancloud.cn/8a/e0/8ae0185425fb734806365df094dd21bf_1913x544.png)
html
~~~
<template>
<div>
<el-table :data="tableData" border :span-method="objectSpanMethod">
<el-table-column type="selection" align="center" width="55" />
<el-table-column prop="taxerName" label="企业名称" align="center" />
<el-table-column prop="taxerId" label="税号" align="center" />
<el-table-column prop="terminalId" label="盘编号" align="center" />
<el-table-column prop="invoiceType" label="发票类型" align="center" width="100px"/>
<el-table-column prop="status" label="抄报状态" align="center" width="100px" />
<el-table-column prop="taxReturnResult" label="抄报结果" align="center" />
<el-table-column prop="unlockResult" label="反写结果" align="center" />
<el-table-column prop="invoiceEndDate" label="开票截止日期" align="center" />
<el-table-column prop="taxReturnDate" label="最新报税日期" align="center" />
<el-table-column fixed="right" label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" size="small">查看详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
~~~
Javascript
~~~
<script>
export default{
data() {
return {
tableData: [
{
"deviceId": "463346577777888888888",
"taxerName": "123",
"taxerId": "4762455555555543333333",
"terminalId": "346537568756876888888",
"invoiceTypes": ["025", "026", "004", "007"],
"rowspan": 1 // rowspan 1:表示不合并
},
{
"deviceId": "645767777754675677777",
"taxerName": "234",
"taxerId": "234444442342344444",
"terminalId": "432524355555333333",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "004",
"status": 3,
"taxReturnResult": "成功",
"unlockResult": "失败",
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 4 // rowspan 4:表示合并下方的三行,共合并四行
},
{
"deviceId": "645767777754675677777",
"taxerName": "234",
"taxerId": "234444442342344444",
"terminalId": "432524355555333333",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "026",
"status": 3,
"taxReturnResult": "成功",
"unlockResult": "失败",
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 0 // rowspan 0:表示已被上面的行合并,该单元格不显示
},
{
"deviceId": "645767777754675677777",
"taxerName": "234",
"taxerId": "234444442342344444",
"terminalId": "432524355555333333",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "007",
"status": 3,
"taxReturnResult": "成功",
"unlockResult": "失败",
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 0 // rowspan 0:表示已被上面的行合并,该单元格不显示
},
{
"deviceId": "645767777754675677777",
"taxerName": "234",
"taxerId": "234444442342344444",
"terminalId": "432524355555333333",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "025",
"status": 3,
"taxReturnResult": "成功",
"unlockResult": "失败",
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 0 // rowspan 0:表示已被上面的行合并,该单元格不显示
},
{
"deviceId": "756465866856767677777",
"taxerName": "555",
"taxerId": "453623465234645555455",
"terminalId": "6436543565455555",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "007",
"status": 3,
"taxReturnResult": null,
"unlockResult": null,
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 3 // rowspan 3:表示合并下方的2行,共合并3行
},
{
"deviceId": "756465866856767677777",
"taxerName": "555",
"taxerId": "453623465234645555455",
"terminalId": "6436543565455555",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "026",
"status": 3,
"taxReturnResult": null,
"unlockResult": null,
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 0 // rowspan 0:表示已被上面的行合并,该单元格不显示
},
{
"deviceId": "756465866856767677777",
"taxerName": "555",
"taxerId": "453623465234645555455",
"terminalId": "6436543565455555",
"invoiceTypes": ["004", "007", "025", "026"],
"invoiceType": "004",
"status": 3,
"taxReturnResult": null,
"unlockResult": null,
"invoiceEndDate": "2019-04-15",
"taxReturnDate": "2019-03-31",
"rowspan": 0 // rowspan 0:表示已被上面的行合并,该单元格不显示
},
{
"deviceId": "46365546555555555",
"taxerName": "666",
"taxerId": "787654545314312",
"terminalId": "789765454151453",
"invoiceTypes": ["004", "026"],
"invoiceType": "026",
"status": 3,
"taxReturnResult": "成功",
"unlockResult": "失败",
"invoiceEndDate": "2019-04-18",
"taxReturnDate": "2019-03-31",
"rowspan": 2// rowspan 2:表示合并下方的1行,共合并2行
},
{
"deviceId": "46365546555555555",
"taxerName": "666",
"taxerId": "787654545314312",
"terminalId": "789765454151453",
"invoiceTypes": ["004", "026"],
"invoiceType": "004",
"status": 3,
"taxReturnResult": "成功",
"unlockResult": "失败",
"invoiceEndDate": "2019-04-18",
"taxReturnDate": "2019-03-31",
"rowspan": 0 // rowspan 0:表示已被上面的行合并,该单元格不显示
}
]
}
},
methods: {
objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
// 之前我这么些判断,有点小蠢...
// if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2 || columnIndex === 3 || columnIndex === 10) {
// 要合并的列的索引
let arr = [0, 1, 2, 3, 10]
// 设置要合并的列
if (arr.indexOf(columnIndex) !== -1) {
// 用于设置合并开始的行号,rowspan 不为 0,不是第一行时, 则该行需要向下合并
if (column.rowSpan !== 0) {
return {
rowspan: row.rowspan, // 要合并的行数
colspan: 1
}
} else {
return {
rowspan: 0, // column.rowspan === 0 隐藏该单元格
colspan: 0
}
}
}
}
}
}
</script>
~~~
<br/>
>[success] ## 每列都有自己的合并方式(合并行)
如图我想写一个这种表格,第一列和第二列的合并行数都不同。
![](https://img.kancloud.cn/f6/8d/f68d834b2929eefa9481ec1780421db7_978x392.png)
html
~~~
<template>
<div>
<el-table :data="permissionData" border :span-method="objectSpanMethod">
<el-table-column prop="deviceId" label="企业名称" align="center" />
<el-table-column prop="taxerName" label="税号" align="center" />
<el-table-column prop="taxerId" label="盘编号" align="center" />
</el-table>
</div>
</template>
~~~
Javascript
~~~
<script>
export default{
data() {
return {
permissionData: [
{
'deviceId': '首页',
'taxerName': '',
'taxerId': '',
'rowspan': [1, 1]
},
{
'deviceId': '管理功能',
'taxerName': '预开审核',
'taxerId': '预开审核管理',
'rowspan': [6, 1]
},
{
'deviceId': '管理功能',
'taxerName': '发票查询',
'taxerId': '已开发票查询',
'rowspan': [0, 3]
},
{
'deviceId': '管理功能',
'taxerName': '发票查询',
'taxerId': '未上传发票查询',
'rowspan': [0, 0]
},
{
'deviceId': '管理功能',
'taxerName': '发票查询',
'taxerId': '验签失败发票查询',
'rowspan': [0, 0]
},
{
'deviceId': '管理功能',
'taxerName': '商户综合管理',
'taxerId': '税控设备列表',
'rowspan': [0, 2]
},
{
'deviceId': '管理功能',
'taxerName': '商户综合管理',
'taxerId': '数据抄报',
'rowspan': [0, 0]
}
]
}
},
methods: {
// 合并表格
objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
let arr = [0, 1]
// 设置要合并的列
if (arr.indexOf(columnIndex) !== -1) {
if (column.rowSpan !== 0) {
// 第一列
if (columnIndex === 0) {
return {
rowspan: row.rowspan[0],
colspan: 1
}
}
// 第二列
else if(columnIndex === 1){
return {
rowspan: row.rowspan[1],
colspan: 1
}
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
}
}
}
</script>
~~~
<br/>
>[success] ## 须知
~~~
以上几种'表格合并',不管是'每列按照同一种方式来合并',还是'每列都有自己的合并方式',他们都有一个
共同点,'同一种方式合并行'需要在数据中返回一个'数值','每列都有自己的合并方式'需要返回一个数组,
并且需要在 'objectSpanMethod'方法中'判断是第几列',每列使用的'rowspan'都不同,上面写的都是
'静态数据',那数据是后台给的动态数据,rowspan又该如何计算,如何把数据整合成想要的格式呢?
~~~
<br/>
>[success] ## 合并表格案例(cv工程师直接来这里)
~~~
下面的例子中如果'想多列合并',而且'根据数据动态合并',就需要手动写一个'this.getSpanArr()'方法,
然后在data中再定义一个'记录行合并数的数组'
~~~
![](https://img.kancloud.cn/f6/8d/f68d834b2929eefa9481ec1780421db7_978x392.png)
html
~~~
<template>
<div>
<el-table :data="permissionData" border :span-method="cellMerge">
<el-table-column prop="deviceId" label="企业名称" align="center" />
<el-table-column prop="taxerName" label="税号" align="center" />
<el-table-column prop="taxerId" label="盘编号" align="center" />
</el-table>
</div>
</template>
~~~
Javascript
~~~
<script>
export default{
data() {
return {
permissionData: [ // 接口数据
{
'deviceId': '首页',
'taxerName': '',
'taxerId': ''
},
{
'deviceId': '管理功能',
'taxerName': '预开审核',
'taxerId': '预开审核管理'
},
{
'deviceId': '管理功能',
'taxerName': '发票查询',
'taxerId': '已开发票查询'
},
{
'deviceId': '管理功能',
'taxerName': '发票查询',
'taxerId': '未上传发票查询',
},
{
'deviceId': '管理功能',
'taxerName': '发票查询',
'taxerId': '验签失败发票查询'
},
{
'deviceId': '管理功能',
'taxerName': '商户综合管理',
'taxerId': '税控设备列表'
},
{
'deviceId': '管理功能',
'taxerName': '商户综合管理',
'taxerId': '数据抄报'
}
],
spanArr: [], // deviceId的合并数
spanArr2: [] // taxerName的合并数
}
},
created(){
this.getSpanArr(this.permissionData,this.spanArr, 'deviceId')
this.getSpanArr(this.permissionData,this.spanArr2, 'taxerName')
},
methods: {
/**
* 记录行合并数方法
* @param {array} data - 后台拿到的数据
* @param {array} arr - 存放每一行记录的合并数
* @param {string} property - 过滤属性是否重复,参数为要过滤的属性
*/
getSpanArr(data, arr, property) {
let pos = 0
for (var i = 0; i < data.length; i++) {
if (i === 0) {
arr.push(1)
pos = 0
} else {
// 判断当前元素与上一个元素是否相同
if (data[i][property] === data[i - 1][property]) {
arr[pos] += 1
arr.push(0)
} else {
arr.push(1)
pos = i
}
}
}
},
// 合并行或列方法
cellMerge({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
else if(columnIndex === 1){
const _row = this.spanArr2[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
}
}
}
</script>
~~~
>[success] ## 简化合并行方法
上面的 **合并行方法** 如果有 **多列需要合并行** ,就要写多个 **this.getSpanArr** 方法,多个 **spanArr** 数组,非常麻烦,可以使用下面这种方法来实现 **合并行**
**tableDemo.vue**
~~~
<template>
<div>
<el-table :data="dataSource" height="846" ref="tableList" border :header-cell-style="{ background: '#f5f7fa' }" :span-method="cellMerges">
<el-table-column label="二级指标" width="200" prop="twoLevel" show-overflow-tooltip align="center" />
<el-table-column label="三级指标" width="240" prop="threeLevel" show-overflow-tooltip align="center" />
<el-table-column label="评分项目" width="240" prop="evaluateProject" show-overflow-tooltip align="center" />
<el-table-column label="评分标准" align="left">
<template slot-scope="scope">
<div style="text-indent: 14px">{{ scope.row.evaluateStandard || '' }}</div>
</template>
</el-table-column>
<el-table-column label="分值" width="90" prop="score" show-overflow-tooltip align="center" />
<el-table-column label="土建" width="90" prop="structureScore" show-overflow-tooltip align="center">
<template slot-scope="scope">
<span>{{ scope.row.structureScore || scope.row.structureScore === 0 ? scope.row.structureScore : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="机电" width="90" show-overflow-tooltip align="center">
<template slot-scope="scope">
<span>{{ scope.row.electroScore || scope.row.electroScore === 0 ? scope.row.electroScore : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="均分" width="90" show-overflow-tooltip align="center">
<template slot-scope="scope">
<span>{{ scope.row.averageScore || scope.row.averageScore === 0 ? scope.row.averageScore : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="150" show-overflow-tooltip align="center">
<template slot-scope="scope">
<el-button type="text" size="small" @click.native.prevent="goGrade(scope.$index, dataSource)"> 评分 </el-button>
<el-button type="text" size="small" @click.native.prevent="goDeduction(scope.$index, dataSource)"> 扣分详情 </el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import Vue from 'vue'
import { Table, TableColumn ,Button } from 'element-ui'
import { mergeRows } from '../js/utils'
// 按需引入
Vue.use(Table)
Vue.use(Button)
Vue.use(TableColumn)
export default {
data() {
return {
dataSource: [
{
twoLevel: '能力指标 27',
threeLevel: '制度建设与落实 15',
evaluateProject: '1.1 责任划分',
secondCode: '27',
thirdCode: '15',
itemCode: '1.1',
standardCode: '1.1.1',
evaluateStandard: '落实了全省隧道责任主体和监管主体,管理职责划分明确,得40分;落实了责任主体和监管主体,但管理职责划分不明确,得20分;落实了责任主体,但管理职责不明确,得10分;责任主体和监管主体不明晰,得0分',
score: 40,
structureScore: '40',
},
{
twoLevel: '能力指标 27',
threeLevel: '制度建设与落实 15',
evaluateProject: '1.2 监管能力',
evaluateStandard: '针对隧道养护管理工作有相关制度或指导性意见,较好,得40分;有相关制度或指导性意见,基本完善,得30分;有相关制度或指导性意见,但不完善,得10分;无相关制度或指导性意见,得0分',
score: 40,
secondCode: '27',
thirdCode: '15',
itemCode: '1.2',
standardCode: '1.2.1',
structureScore: '40',
}
]
}
},
methods: {
cellMerges({ rowIndex, columnIndex}) {
const mergeCfg = [
{ searchKey: 'secondCode', columnIndex: 0 },
{ searchKey: 'thirdCode', columnIndex: 1 },
{ searchKey: 'itemCode', columnIndex: 2 }
]
return mergeRows(rowIndex, columnIndex, this.dataSource, mergeCfg)
}
}
}
</script>
~~~
**合并行方法**
~~~
/**
* 合并行方法
* @param {*} rowIndex 行索引
* @param {*} columnIndex 列索引
* @param {*} dataSource 数据源
* @param {*} mergeCfg 合并配置 例如:[{searchKey: 'score', columnIndex: 0 }] searchKey:需检索的属性,columnIndex:代表要合并的列数
*/
export function mergeRows(rowIndex, columnIndex, dataSource, mergeCfg) {
for (let item of mergeCfg) {
let searchKey = item.searchKey
if (columnIndex === item.columnIndex) { // 要合并的列
if (rowIndex !== 0 && dataSource[rowIndex][searchKey] === dataSource[rowIndex - 1][searchKey]) { // 非第一行合并规则(非第一行,并且上一行跟当前行值相等,如果不相等就走else)
return [0, 0]
} else { // 第一行合并规则
let rowIndexCount = rowIndex
let count = 0
while (rowIndexCount + 1 < dataSource.length) { // 用当前行数据跟后续行数数据对比
if (dataSource[rowIndexCount + 1][searchKey] === dataSource[rowIndexCount][searchKey]) {
rowIndexCount++
count++
} else { // 数据不相等跳出循环
break
}
}
return [count + 1, 1]
}
}
}
}
~~~
- vue复选框逻辑
- get请求给后台传数组
- 提交表单时传值参数处理方案
- Element ui上传图片功能
- async和await的使用
- 时间戳转换
- 日期格式转换时间戳
- 时间戳转换日期格式
- 对深拷贝的认知总结
- vue-右键菜单功能
- textarea中换行、回车、空格的识别与处理
- element ui表格合并
- 合并行(上下行)
- 双层for循环
- 数组去重
- 瀑布流
- 前端多条件筛选
- 闭包的理解
- 改变this指向
- vue单选框逻辑
- 对象数组根据某个属性来进行排序
- vscode插件整理
- 对象数组多条件去重
- Blob类型数据转换Json数据类型
- Element ui做批量上传功能
- 前端cookie和后端cookie
- 强制转换https协议
- 给事件传额外参数
- 树形结构数据处理
- 查找所有父级数据
- 根据id筛选单条数据
- 动态引入阿里图标库
- 四舍五入
- 封装一个Promise.allSettled方法
- 判断输入框内是否有emoji表情
- element-ui的popover组件位置偏移
- formData上传文件时,携带【数组对象参数】
- 前端解压压缩包(zip)解压后上传解压的文件
- element ui表格列相同解决办法
- elementUI,table复选框多选,翻页/切换条数时保持选中状态
- cookie 和 token 的区别