【亲测有效】element-ui table :span-method(行数和列数合并)
【最新最详细】element-ui table :span-method(行数和列数合并)element-ui官网中关于行合并的例子是根据行索引进行合并的,这显然不符合我们日常开发需求,因为通常我们table中的数据都是动态生成的,所以需要做一些改造以达到我们要实现的需求。首先,我们来解读一下官网实例中的各个参数的意义:研究这个实例后不难发现,实现合并行的方法其实在每一行数据渲染的时候都会执行,只
【亲测有效】element-ui table :span-method(行数和列数合并)
文章目录
1.官方示例解读
element-ui官网中关于行合并的例子是根据行索引进行合并的,这显然不符合我们日常开发需求,因为通常我们table中的数据都是动态生成的,所以需要做一些改造以达到我们要实现的需求。
首先,我们来解读一下官网实例中的各个参数的意义:
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) { //用于设置要合并的列
if (rowIndex % 2 === 0) { //用于设置合并开始的行,求余数=0,则执行方法体中的代码
return {
rowspan: 2, //合并的行数
colspan: 1 //合并的列数,设为0则直接不显示
};
} else {
return {
rowspan: 0,
colspan: 0
};
}
}
}
研究这个实例后不难发现,实现合并行的方法其实在每一行数据渲染的时候都会执行,只不过在渲染过程中我们设置了它合并的行数和列数,以得到不同的效果。
对于合并行数和列数,我认为有两种场景。
2.开发实例
我是以原生的HTML来作为示例,和Webpack用法一样的。如果是使用原生的HTML,则需要提前下载vuejs、element-ui。(如果是使用Webpack,请忽略)
<!--引入 element-ui 的样式,-->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 必须先引入vue, 后使用element-ui -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<!-- 引入element 的组件库-->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
2.1实例一(后端返回数据设置合并的行数和列数)
第一种场景:后端返回数据的同时也返回合并的行数和列数,直接根据后端返回的结果进行设置合并的行数和列数。(这种的业务场景会复杂一些,不过因需求而异)
HTML:
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="format-detection" content="telephone=no" />
<title>后端返回合并的行数和列数结果</title>
<script src="../Common/Vue+ElementUi/vue.js"></script>
<script src="../Common/Vue+ElementUi/vue2.6.11.js"></script>
<link rel="stylesheet" href="../Common/Vue+ElementUi/element-ui.css">
<script src="../Common/Vue+ElementUi/element-ui.js"></script>
<script src="../JS/common.js"></script>
</head>
<body leftMargin="0" topMargin="0">
<div id="app">
<el-row style="margin:5px 5px 5px 20px;">
<el-col :span="8">
</el-col>
<el-col :span="8" style="text-align: right;">
</el-col>
</el-row>
<el-table :data="tableData" style="width: 100%" border height="100%" :cell-style="cellStyle" :span-method="objectSpanMethod">
<el-table-column label="用户地址信息" align="center">
<el-table-column prop="Province.Value" label="省份" width="120"></el-table-column>
<el-table-column label="地址" width="120" align="center">
<el-table-column prop="City.Value" label="市" width="120"></el-table-column>
<el-table-column prop="Area.Value" label="县" width="120"></el-table-column>
<el-table-column prop="Name.Value" label="姓名" width="120"></el-table-column>
<el-table-column prop="Address.Value" label="详细地址" width="120"></el-table-column>
</el-table-column>
</el-table-column>
</el-table-column>
</el-table>
</div>
</body>
Script代码:
<script>
// 该vue对象,绑定了页面中id是app的那个div
new Vue(
{
el: '#app', //element
data: {
tableData:[], //表格数据
columnOrder:[ //列字段排序,用于合并行数和列数使用
"Province",
"City",
"Area",
"Name",
"Address",
]
},
mounted(){
this.Init();
},
methods:{
//初始化
Init(){
const that = this;
that.tableData = [
{
"Province":{
"Value":"广东省",
"RowSpan":3,
"ColumnSpan":1,
"CellStyle":{
"font-weight":800,
"background-color":"#fff"
}
},
"City":{
"Value":"广州市",
"RowSpan":2,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Area":{
"Value":"天河区",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Name":{
"Value":"张三",
"RowSpan":2,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Address":{
"Value":"测试地址1",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
}
},
{
"Province":{
"Value":"广东省",
"RowSpan":0,
"ColumnSpan":0,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"City":{
"Value":"广州市",
"RowSpan":0,
"ColumnSpan":0,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Area":{
"Value":"白云区",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Name":{
"Value":"张三",
"RowSpan":0,
"ColumnSpan":0,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Address":{
"Value":"测试地址2",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
}
},
{
"Province":{
"Value":"广东省",
"RowSpan":0,
"ColumnSpan":0,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"City":{
"Value":"佛山市",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Area":{
"Value":"禅城区",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Name":{
"Value":"李四",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
},
"Address":{
"Value":"测试地址3",
"RowSpan":1,
"ColumnSpan":1,
"CellStyle":{
"font-weight":400,
"background-color":"#fff"
}
}
}
];
},
//单元格样式
cellStyle({ row, column, rowIndex, columnIndex }) {
return row[this.columnOrder[columnIndex]].CellStyle;
},
//合并行数和列数
objectSpanMethod({ row, column, rowIndex, columnIndex }){
let obj = {
rowspan: row[this.columnOrder[columnIndex]].RowSpan,
colspan: row[this.columnOrder[columnIndex]].ColumnSpan
}
return obj;
}
}
}
);
</script>
执行后的效果截图:
功能实现讲解:
columnOrder:列字段排序集合,因为数据排序无法固定,故需借此来固定取字段的RowSpan、ColumnSpan。
tableData中的RowSpan:该行该列需要合并的行数,0则不显示。
tableData中的ColumnSpan:该行该列需要合并的列数,0则不显示。
2.2实例二(前端判断内容设置合并的行数和列数)
第二种场景:前端通过判断上下行的单元格、同行的左右单元格的内容,如果内容相等则要合并行数或列数。
HTML:
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="format-detection" content="telephone=no" />
<title>报表测试</title>
<script src="../Common/Vue+ElementUi/vue.js"></script>
<script src="../Common/Vue+ElementUi/vue2.6.11.js"></script>
<link rel="stylesheet" href="../Common/Vue+ElementUi/element-ui.css">
<script src="../Common/Vue+ElementUi/element-ui.js"></script>
<script src="../JS/common.js"></script>
</head>
<body leftMargin="0" topMargin="0">
<div id="app">
<el-row style="margin:5px 5px 5px 20px;">
<el-col :span="8">
</el-col>
<el-col :span="8" style="text-align: right;">
</el-col>
</el-row>
<el-table :data="tableData" style="width: 100%" border height="100%" :span-method="objectSpanMethod">
<el-table-column label="用户地址信息" align="center">
<el-table-column prop="Province" label="省份" width="120"></el-table-column>
<el-table-column label="地址" width="120" align="center">
<el-table-column prop="City" label="市" width="120"></el-table-column>
<el-table-column prop="Area" label="县" width="120"></el-table-column>
<el-table-column prop="Name" label="姓名" width="120"></el-table-column>
<el-table-column prop="Address" label="详细地址" width="120"></el-table-column>
</el-table-column>
</el-table-column>
</el-table-column>
</el-table>
</div>
</body>
Script代码:
<script>
<script>
// 该vue对象,绑定了页面中id是app的那个div
new Vue(
{
el: '#app', //element
data: {
tableData:[], //表格数据
columnOrder:[ //列字段排序,用于合并行数和列数
"Province",
"City",
"Area",
"Name",
"Address",
]
},
mounted(){
this.Init();
},
methods:{
//初始化
Init(){
const that = this;
that.tableData = [
{
"Province":"广东省",
"City":"佛山市",
"Area":"禅城区",
"Name":"张三",
"Address":"测试地址1"
},{
"Province":"广东省",
"City":"佛山市",
"Area":"南海区",
"Name":"张三",
"Address":"测试地址2"
},{
"Province":"广东省",
"City":"广州市",
"Area":"白云区",
"Name":"李四",
"Address":"测试地址3"
},{
"Province":"北京市",
"City":"北京市",
"Area":"顺义区",
"Name":"王五",
"Address":"测试地址4"
},
];
},
//合并行数和列数
objectSpanMethod({ row, column, rowIndex, columnIndex }){
const that = this;
let obj = {
rowspan:1,
colspan:1
}
obj = that.getRowSpanQty(row,rowIndex,columnIndex,obj);
obj = that.getColumnSpanQty(row,rowIndex,columnIndex,obj);
return obj;
},
//获取合并列数
getRowSpanQty(row,rowIndex,columnIndex,obj){
const that = this;
if(rowIndex == 0){
//当第一行,就循环判断一下行是否存在相同内容,是则行数+1
let isNeedNextRow = true; //是否继续循环下一行同一个单元格
for(let i =0;i < that.tableData.length;i++){
if(rowIndex != i && isNeedNextRow != false){
let data = that.tableData[i];
if(data[this.columnOrder[columnIndex]] == row[this.columnOrder[columnIndex]]){
obj.rowspan++;
isNeedNextRow = true;
}else{
isNeedNextRow = false;
}
}
}
}else{
let data = that.tableData[rowIndex - 1];
if(data[this.columnOrder[columnIndex]] == row[this.columnOrder[columnIndex]]){
//当不是第一行,则判断当前单元格与上一行的当前单元格是否一致,一致则不显示
obj.rowspan = 0;
obj.colspan = 0;
}
}
return obj;
},
//获取合并列数
getColumnSpanQty(row,rowIndex,columnIndex,obj){
const that = this;
let isNeedNextColumn = true; //是否继续循环当前行下一个单元格
for(let i = columnIndex;i < this.columnOrder.length;i++){
if(isNeedNextColumn != false){
let columnName = this.columnOrder[i+1];
if(row[this.columnOrder[columnIndex]] == row[columnName]){
//当前行的单元格=当前行的下一个单元格,则列数+1
obj.colspan++;
isNeedNextColumn = true;
}else{
isNeedNextColumn = false;
}
}
}
if(row[this.columnOrder[columnIndex]] == row[this.columnOrder[columnIndex-1]]){
//当当前行的当前单元格=当前行的上一个单元格,则0不显示
obj.rowspan = 0;
obj.colspan= 0;
}
return obj;
}
}
}
);
</script>
执行后的效果截图:
功能实现讲解:
columnOrder:列字段排序集合,因为数据排序无法固定,故需借此来固定排序方便取数。
getRowSpanQty:获取行需要的合并数。
getColumnSpanQty:获取列需要的合并数。
重点是要理解getRowSpanQty和getColumnSpanQty方法。
那么这两种场景的实现应该能够满足大家日常开发的需求,希望可以帮助到大家,共勉。
声明
本篇文章的内容完全个人原创,如其他文档有与本章内容雷同,均为抄袭本篇文章。请尊重原创!
更多推荐
所有评论(0)