因为本人就喜欢粘了直接能用的demo, 在查找这个实现的时候看了太多人的废话 所以想要写一个在vue中粘贴直接能用的代码
长这样:左边是table标签 右边是el-table
代码:
<template>
<div class="project-detail" ref="content">
<div
class="table-wrapper"
style="display: flex; justify-content: space-between"
>
<!-- table 标签版 -->
<table class="table">
<!-- 表头 -->
<tr class="tr head">
<td style="width: 80px">序号</td>
<td>姓名</td>
<td>案号</td>
<td>年龄</td>
<td>体重</td>
</tr>
<!-- 表体 -->
<tr v-for="(row, idx) in tableData" :key="idx">
<td>
{{ idx + 1 }}
</td>
<td v-if="row.nameSpan" :rowspan="row.nameSpan">
{{ row.name }}
</td>
<td v-if="row.caseNumSpan" :rowspan="row.caseNumSpan">
{{ row.caseNum }}
</td>
<td v-if="row.ageSpan" :rowspan="row.ageSpan">
{{ row.age }}
</td>
<td v-if="row.weightSpan" :rowspan="row.weightSpan">
{{ row.weight }}
</td>
</tr>
</table>
<!-- elementui版 -->
<div style="width: 600px; border: 1px solid">
<el-table :data="tableData" :span-method="objectSpanMethod" border>
<el-table-column label="序号" width="80">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" />
<el-table-column prop="caseNum" label="案号" align="center" />
<el-table-column prop="age" label="年龄" align="center" />
<el-table-column prop="weight" label="体重" align="center" />
</el-table>
</div>
</div>
</div>
</template>
<script>
export default {
name: "demo",
data() {
return {
tableData: [
{ name: "张三", caseNum: 2, age: 21, weight: 90 },
{ name: "张三", caseNum: 2, age: 21, weight: 90 },
{ name: "张三", caseNum: 2, age: 21, weight: 90 },
{ name: "张三", caseNum: 2, age: 25, weight: 90 },
{ name: "李四", caseNum: 8, age: 30, weight: 60 },
{ name: "李四", caseNum: 8, age: 25, weight: 60 },
{ name: "李四", caseNum: 8, age: 25, weight: 60 },
{ name: "李四", caseNum: 8, age: 23, weight: 60 },
{ name: "王五", caseNum: 8, age: 23, weight: 60 },
{ name: "王五", caseNum: 7, age: 30, weight: 60 },
{ name: "王五", caseNum: 7, age: 30, weight: 60 },
{ name: "王五", caseNum: 7, age: 25, weight: 70 },
{ name: "王五", caseNum: 7, age: 25, weight: 70 },
{ name: "王五", caseNum: 7, age: 25, weight: 70 },
],
};
},
methods: {
rowspanMethod(list) {
for (let i = 0; i < list.length; i++) {
let startRow;
// 需要合并的行数
let nameSpan = 1;
// 循环到最后时
if (i === list.length - 1) {
// 当最后一行和倒数第二行属性不同 跳出循环
if (list[i].name !== list[i - 1].name) {
list[i].nameSpan = nameSpan;
}
break;
}
// 内层循环求需要合并的数量
for (let j = i; j < list.length - 1; j++) {
// 循环结束的行数
startRow = j;
// 属性相同则++
if (list[j].name === list[j + 1].name) {
nameSpan++;
} else {
// 属性不同跳出
break;
}
}
// 为数组添加你定义的rowspan属性
list[i].nameSpan = nameSpan;
// 控制外循环从内循环结束的行数开始
i = startRow;
}
for (let i = 0; i < list.length; i++) {
let startRow;
let caseNumSpan = 1;
if (i === list.length - 1) {
// 因为要基于前面姓名相同才可以进行合并所以要加上name条件
if (
list[i].caseNum !== list[i - 1].caseNum &&
list[i].name !== list[i - 1].name
) {
list[i].caseNumSpan = caseNumSpan;
}
break;
}
for (let j = i; j < list.length - 1; j++) {
startRow = j;
// 这里也要加上条件
if (
list[j].caseNum === list[j + 1].caseNum &&
list[j].name === list[j + 1].name
) {
caseNumSpan++;
} else {
break;
}
}
list[i].caseNumSpan = caseNumSpan;
i = startRow;
}
for (let i = 0; i < list.length; i++) {
let startRow;
let ageSpan = 1;
if (i === list.length - 1) {
// 加上name caseNum 条件
if (
list[i].age !== list[i - 1].age &&
list[i].caseNum !== list[i - 1].caseNum &&
list[i].name !== list[i - 1].name
) {
list[i].ageSpan = ageSpan;
}
break;
}
for (let j = i; j < list.length - 1; j++) {
// 记录循环结束的行数
startRow = j;
// 加上name caseNum 条件
if (
list[j].age === list[j + 1].age &&
list[j].caseNum === list[j + 1].caseNum &&
list[j].name === list[j + 1].name
) {
ageSpan++;
} else {
break;
}
}
list[i].ageSpan = ageSpan;
i = startRow;
}
for (let i = 0; i < list.length; i++) {
let startRow;
let weightSpan = 1;
if (i === list.length - 1) {
// 加上name caseNum age条件
if (
list[i].age !== list[i - 1].age &&
list[i].caseNum !== list[i - 1].caseNum &&
list[i].name !== list[i - 1].name &&
list[i].weight !== list[i - 1].weight
) {
list[i].weightSpan = weightSpan;
}
break;
}
for (let j = i; j < list.length - 1; j++) {
startRow = j;
// 加上name caseNum age条件
if (
list[j].age === list[j + 1].age &&
list[j].caseNum === list[j + 1].caseNum &&
list[j].name === list[j + 1].name &&
list[j].weight === list[j + 1].weight
) {
weightSpan++;
} else {
break;
}
}
list[i].weightSpan = weightSpan;
i = startRow;
}
this.tableData = list;
},
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// 姓名列合并
if (column.property === "name") {
const currentValue = row.name;
const prevRow = this.tableData[rowIndex - 1];
if (prevRow && prevRow.name === currentValue) {
// 隐藏重复单元格
return [0, 0];
} else {
// 计算相同的连续行数
let rowspan = 1;
for (let i = rowIndex + 1; i < this.tableData.length; i++) {
if (this.tableData[i].name === currentValue) {
rowspan++;
} else {
break;
}
}
return [rowspan, 1];
}
}
// 案号列合并
if (column.property === "caseNum") {
const currentValue = row.caseNum;
const prevRow = this.tableData[rowIndex - 1];
// 案号列合并有条件,需姓名相同
if (
prevRow &&
prevRow.caseNum === currentValue &&
row.name === prevRow.name
) {
// 隐藏重复单元格
return [0, 0];
} else {
// 计算相同的连续行数
let rowspan = 1;
for (let i = rowIndex + 1; i < this.tableData.length; i++) {
if (
this.tableData[i].caseNum === currentValue &&
row.name === this.tableData[i].name
) {
rowspan++;
} else {
break;
}
}
return [rowspan, 1];
}
}
//年龄列合并
if (column.property === "age") {
const currentValue = row.age;
const prevRow = this.tableData[rowIndex - 1];
// 年龄列合并有条件,需案号、姓名相同
if (
prevRow &&
prevRow.age === currentValue &&
row.caseNum === prevRow.caseNum &&
row.name === prevRow.name
) {
// 隐藏重复单元格
return [0, 0];
} else {
let rowspan = 1;
for (let i = rowIndex + 1; i < this.tableData.length; i++) {
if (
this.tableData[i].age === currentValue &&
row.caseNum === this.tableData[i].caseNum &&
row.name === this.tableData[i].name
) {
rowspan++;
} else {
break;
}
}
return [rowspan, 1];
}
}
if (column.property === "weight") {
const currentValue = row.weight;
const prevRow = this.tableData[rowIndex - 1];
if (
prevRow &&
prevRow.weight === currentValue &&
row.caseNum === prevRow.caseNum &&
row.name === prevRow.name &&
row.age === prevRow.age
) {
return [0, 0]; // 隐藏重复单元格
} else {
let rowspan = 1;
for (let i = rowIndex + 1; i < this.tableData.length; i++) {
if (
this.tableData[i].weight === currentValue &&
row.caseNum === this.tableData[i].caseNum &&
row.name === this.tableData[i].name &&
row.age === this.tableData[i].age
) {
rowspan++;
} else {
break;
}
}
return [rowspan, 1];
}
}
},
},
created() {
this.rowspanMethod(this.tableData);
},
};
</script>
<style lang="less" scoped>
.project-detail {
background: #f5f5f5;
min-height: auto;
padding-bottom: 0.2rem;
.table {
width: 600px;
display: table;
background: #fff;
border-collapse: collapse;
tr {
display: table-row;
td {
border: 1px solid;
text-align: center;
display: table-cell;
padding: 8px 6px;
white-space: nowrap;
color: #1c3375;
font-size: 13px;
&.right {
text-align: right;
}
}
&.head {
font-weight: bold;
background: #fef6ea;
color: #1c3375;
font-size: 13px;
td {
border: 1px solid transparent;
}
}
}
}
}
</style>
el-table 主要就是使用了 :span-method="objectSpanMethod" 不明白自己打印就知道都是什么东西了 然后按照你需求调整一下 表格列prop记得写对 不然不生效
table标签 主要就是使用了rowspan属性 然后结合v-if 隐藏合并的 所以需要把你表格数据都过一遍 添加上标识
我写的时候还发现需要写序号 不然这数据就少了 但是不知道怎么回事啊啊 有好心人可以告诉我也ok
方法谁有更好的方法可以自己整理 哥们水平就是个百度cxy 每天复制粘贴