Element-ui表格合并,并添加合计、小计功能
#最近Vue项目需要用到表格合并功能、合并小计和合并功能(用于数据的展示),所以进行记录一下,废话少说(本人也是小白),贴图一张(效果图)
首先是贴HTML页面的代码
<template>
<div class="container">
<el-table
:data="dataT"
border
:span-method="arraySpanMethod"
@selection-change="handleSelectionChange"
style="width: 100%">
<el-table-column
fixed
prop="orderNumber"
label="序号"
width="150">
</el-table-column>
<el-table-column
prop="categories"
label="分类"
width="120">
</el-table-column>
<el-table-column
prop="produceName"
label="名称"
width="120">
</el-table-column>
<el-table-column
prop="referenceBrand"
label="品牌"
width="120">
<template slot-scope="scope">
<div v-show="!scope.row.isEdit">
{{ scope.row.referenceBrand }}
</div>
<div v-show="scope.row.isEdit">
<el-input size="small" v-model="scope.row.referenceBrand" placeholder="请输入参考品牌"
></el-input>
</div>
</template>
</el-table-column>
<el-table-column
prop="eimac"
label="型号"
width="120">
<template slot-scope="scope">
<div v-show="!scope.row.isEdit">
{{ scope.row.eimac }}
</div>
<div v-show="scope.row.isEdit">
<el-input size="small" v-model="scope.row.eimac" placeholder="请输入参考类型"
></el-input>
</div>
</template>
</el-table-column>
<el-table-column
prop="measurement"
label="单位"
width="120">
</el-table-column>
<el-table-column
prop="quantity"
label="数量"
width="120">
<template slot-scope="scope">
<div v-show="!scope.row.isEdit">
{{ scope.row.quantity }}
</div>
<div v-show="scope.row.isEdit">
<el-input size="small" v-model="scope.row.quantity" placeholder="请输入采购数量"
></el-input>
</div>
</template>
</el-table-column>
<el-table-column
prop="OriginRequestment"
label="要求"
width="120">
</el-table-column>
<el-table-column
prop="spotRequirement"
label="要求"
width="120">
</el-table-column>
<el-table-column
prop="originalWp"
label="质保期(年)"
width="120">
<template slot-scope="scope">
<div v-show="!scope.row.isEdit">
{{ scope.row.originalWp }}
</div>
<div v-show="scope.row.isEdit">
<el-input size="small" v-model="scope.row.originalWp" placeholder="请输入原厂质保期"
></el-input>
</div>
</template>
</el-table-column>
<el-table-column
prop="specifications"
label="技术"
width="120">
<template slot-scope="scope">
<div v-show="!scope.row.isEdit">
{{ scope.row.specifications }}
</div>
<div v-show="scope.row.isEdit">
<el-input size="small" v-model="scope.row.specifications" placeholder="请输入技术指标"
></el-input>
</div>
</template>
</el-table-column>
<!-- <el-table-column
fixed="right"
label="操作"
width="120">
<template slot-scope="scope">
<el-button
@click.native.prevent="addButton(scope.$index, dataT)"
type="text"
size="small">
添加
</el-button>
<el-button type="text" size="small" @click.native.prevent="editButton(scope.$index, dataT)">
<template>
<span v-show="!scope.row.isEdit">编辑</span>
<span v-show="scope.row.isEdit">完成</span>
</template>
</el-button>
<el-button
@click.native.prevent="deleteRow(scope.$index, dataT)"
type="text"
size="small">
移除
</el-button>
</template>
</el-table-column> -->
</el-table>
</div>
</template>
css代码
<style lang="css">
.container{
margin: auto;
width: 71%;
}
.el-table td, .el-table th{
text-align: center !important;
}
</style>
接下来是方法的调用(表格合并的重点)
<script>
let _self;
export default {
data() {
return {
spanArr:[],
items:[],
dataT:[],
indexss:0,
pos:0
}
},
computed: {
},
created(){
_self = this;
},
mounted(){
_self.initDataForhttp();
},
methods: {
initDataForhttp(){
//封装后台数据
let curItems=[
{orderNumber:'1',categories:"电子",produceName:'显示',referenceBrand:'三星',eimac:'C32JG52QQC',measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:'是',originalWp:"3",specifications:"",isEdit:false},
{orderNumber:'1',categories:"电子",produceName:'显示',referenceBrand:'DELL',eimac:'U3219Q',measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:'是',originalWp:"3",specifications:"",isEdit:false},
{orderNumber:'1',categories:"电子",produceName:'显示',referenceBrand:'HP',eimac:'3219Q',measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:'是',originalWp:"3",specifications:"",isEdit:false},
{orderNumber:'2',categories:"办公",produceName:"打印纸",referenceBrand:"无",eimac:"无",measurement:'本',quantity:1000,OriginRequestment:'国产',spotRequirement:'是',originalWp:"无",specifications:"",isEdit:false},
// {orderNumber:'3',categories:"办公设备",produceName:'小计:',referenceBrand:10000,eimac:10000,measurement:'002',quantity:8,OriginRequestment:'',spotRequirement:'',originalWp:3,specifications:"",isEdit:false},
{orderNumber:'3',categories:"设备",produceName:'笔记',referenceBrand:"三星",eimac:"C32JG52QQC",measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:"是",originalWp:"3",specifications:"",isEdit:false},
{orderNumber:'3',categories:"设备",produceName:'笔记',referenceBrand:"DELL",eimac:"U3219Q",measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:"是",originalWp:"3",specifications:"",isEdit:false},
{orderNumber:'3',categories:"设备",produceName:'笔记',referenceBrand:"HP",eimac:"3219Q",measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:"是",originalWp:"3",specifications:"",isEdit:false},
{orderNumber:'4',categories:"电子",produceName:'显示',referenceBrand:'三星',eimac:'C32JG52QQC',measurement:'台',quantity:8,OriginRequestment:'国产',spotRequirement:'是',originalWp:"3",specifications:"",isEdit:false}
// {orderNumber:'5',categories:"",produceName:'合计:',referenceBrand:10000,eimac:10000,measurement:'003',quantity:8,OriginRequestment:'',spotRequirement:'',originalWp:"3",specifications:""}
]
_self.dataT = curItems;
},
arraySpanMethod({row, column, rowIndex, columnIndex}){
const that = this;
let num = 0;
var key = column.property;
var val = that.dataT[rowIndex][key];
var xuhao = that.dataT[rowIndex]['orderNumber'];
for (let i in that.dataT) { //遍历items
for (let j in that.dataT[i]) { //再遍历item的key
if (j == 'orderNumber' || j == 'categories' || j == 'produceName' || j==="referenceBrand" || j==="measurement" || j==="quantity"
|| j==="OriginRequestment" || j==="spotRequirement" || j==="originalWp" || j==="specifications") { //如果j等于这三者其中一个
if (key === j && val === that.dataT[i][j]) { //再判断j是否等于key,并且val等于items里面的items[i][j]的值
if (that.dataT[i][j] == '小计:' || that.dataT[i][j] == '合计:') { //如果等于则判断是否未小计、合计
return;//如果是,则不用合并列
}
var index = that.dataT.findIndex(item=>{
return item[key] == val && item['orderNumber'] === xuhao;
})
if(rowIndex==index){
//证明是第一个,算出需要合并多少行
var numss = that.getNumForValue(key,val,xuhao);
return{
rowspan:numss,
colspan:1
}
}else{
//其他的隐藏
return{
rowspan:0,
colspan:0
}
}
}
}
}
}
},
//得到重复值的数量
getNumForValue(key,val,xuhao){
const that = this;
let num = 0;
for (let i in that.dataT) { //遍历items
for (let j in that.dataT[i]) { //再遍历item的key
if (j == 'orderNumber' || j == 'categories' || j == 'produceName' || j==="referenceBrand" || j==="measurement" || j==="quantity"
|| j==="OriginRequestment" || j==="spotRequirement" || j==="originalWp" || j==="specifications") { //如果j等于这三者其中一个
if (key === j && val === that.dataT[i][j] && xuhao===that.dataT[i]['orderNumber']) { //再判断j是否等于key,并且val等于items里面的items[i][j]的值
if (that.dataT[i][j] == '小计:' || that.dataT[i][j] == '合计:') { //如果等于则判断是否未小计、合计
console.log(val+":"+num)
return 0;//如果是,则不用合并列
}
num++;//如果不是。则合并,合并数加1
}
}
}
}
return num;
},
rowSpanF: function (key, val) {
console.log(val);
const that = this;
let num = 0;
for (let i in that.items) { //遍历items
for (let j in that.items[i]) { //再遍历item的key
if (j == 'feeName' || j == 'projectName' || j == 'produceName') { //如果j等于这三者其中一个
if (key === j && val === that.items[i][j]) { //再判断j是否等于key,并且val等于items里面的items[i][j]的值
if (that.items[i][j] == '小计:' || that.items[i][j] == '合计:') { //如果等于则判断是否未小计、合计
console.log(val+":"+num)
return//如果是,则不用合并列
}
num++;//如果不是。则合并,合并数加1
}
}
}
}
// console.log(val+":"+num);
if(num==0){//如果为o,则为一列
return 1
}
return num;
},
// deleteRow(index, rows) {
// this.dataT.splice(index, 1);
// // this.dataT.splice(index,1);
// this.$forceUpdate();
// },
// editButton(index, rows){
// this.dataT[index].isEdit = !this.dataT[index].isEdit;
// console.log(this.dataT[index].isEdit)
// },
// addButton(index, rows){
// var obj={
// "orderNumber": this.dataT[index].orderNumber,
// "categories": this.dataT[index].categories,
// "produceName": this.dataT[index].produceName,
// "referenceBrand": "",
// "eimac": "",
// "measurement": this.dataT[index].measurement,
// "quantity": this.dataT[index].quantity,
// "OriginRequestment": this.dataT[index].OriginRequestment,
// "spotRequirement": this.dataT[index].spotRequirement,
// "originalWp": this.dataT[index].originalWp,
// "specifications": this.dataT[index].specifications,
// "isEdit": true
// }
// this.dataT.splice(index+1,0,obj);
// },
handleSelectionChange(val) {
this.dataT = val;
// console.log("大风呼呼uuu");
}
}
}
</script>
解释
代码已经全部贴出来了,注释的是动态增加、删除、编辑功能,不过由于项目暂时用不到,所以注释掉,接下来解释一下方法的调用:
- 数据的格式的加载,调用initDataForhttp()方法进行数据获取(如果你是拿后台的数据进行显示,可以在此方法进行请求,然后把数据封装成为上面的格式)
- 单元格的合并(重点),首先是调用 :span-method=“arraySpanMethod”,arraySpanMethod()方法里面就是单元格合并,首先我的思路是,先判断表格的数据是否在同一个序号里面是否拥有相同的值。如果拥有,则算出来它拥有多少个相同的值,则判断是否是第一个(使用数组的findIndex方法得到下标,判断行id是否跟下标相同,如果相同则为第一个,否则不是(需要将该表格列进行隐藏)),如果没有则不用管