原始表格及代码
html
复制代码
<el-table
:data="tableData"
class="myTable"
header-row-class-name="tableHead"
>
<el-table-column prop="date" label="日期"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="project" label="项目"> </el-table-column>
<el-table-column prop="address" label="地址" min-width="200">
</el-table-column>
</el-table>
javascript
复制代码
// 模拟数据接口请求并排序
getDataMock() {
for (var i = 0; i < 10; i++) {
let randomDay = Math.floor(Math.random() * 5 + 1);
this.tableData.push({
date: "2024-12-" + randomDay,
name: "王小虎" + i,
project: "项目" + i,
address: "上海市普陀区金沙江路 " + i + " 弄",
});
}
this.tableData.sort((a, b) => {
let time1 = new Date(a.date).getTime();
let time2 = new Date(b.date).getTime();
return time1 - time2;
});
},
css
复制代码
.myTable {
width: 700px;
margin: 0 auto;
border-radius: 20px;
.tableHead {
.el-table__cell {
background-color: #bee7c5;
color: #264f30;
border-bottom: none;
&:first-child {
background: #435f5b;
color: #fff;
}
}
}
.el-table__body {
.el-table__row {
.el-table__cell {
background: #f7f7f7;
border-bottom: 1px solid #dcdcdc;
&:first-child {
background: #acb2d9;
color: #32405b;
font-weight: bold;
border-bottom: 1px solid #32405b;
}
}
}
}
}
合并行
- 需要动态计算表格数据的合并行数
- 如图所示,需要得到如下的 rowspan
- 计算表格数据每行的 rowspan
javascript
复制代码
// 动态计算合并行的索引
getTableDataSpan(arr) {
let spanData = []; // 数据数组的 rowspan 集合
// rowspan > 1,合并行
// rowspan == 1,单独行,不参与合并
// rowspan == 0,被合并的行
let lastRowIndex = 0; // 记录索引
arr.forEach((item, index) => {
if (index == 0) {
// 第一行,默认认为不参与合并,记录为 1
spanData.push(1);
} else {
if (item.date == arr[index - 1].date) {
// 当前行的 date 与上一行的 date 相同,即当前行 的 rowspan 需要被记为 0
spanData.push(0);
// 向前找上次记录的索引,即需要当前行合并过去的目标行,使目标行的 rowspan 值加一
spanData[lastRowIndex] += 1;
} else {
// 当前行的 date 与上一行的 date 不相等,则当前行的 rowspan 记录为 1
spanData.push(1);
// 暂且记录一下 lastRowIndex
// 如果下一行与当前行的 date 值相同,就会合并到当前行,否则会更新 lastRowIndex 的值,进行下次对比
lastRowIndex = index;
}
}
});
return {
spanData: spanData,
lastRowIndex: lastRowIndex,
};
},
html
复制代码
<el-table
:data="tableData"
class="myTable"
header-row-class-name="tableHead"
:span-method="spanMethod"
>
...
javascript
复制代码
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
// 只有第一列需要合并,所以限定为 columnIndex === 0
// 获取当前行的 rowspan
let rowspan = this.getTableDataSpan(this.tableData).spanData[rowIndex];
let colspan = rowspan === 0 ? 0 : 1; // 被合并到其他行,需要为 colspan 赋值为 0,否则为 1
return {
rowspan: rowspan,
colspan: colspan,
};
}
},
样式调整优化
- 上述代码得到如下效果
- 原因是被合并的行,删掉了首列,被赋予了 first-child 的样式
html
复制代码
<el-table
:data="tableData"
class="myTable"
header-row-class-name="tableHead"
:span-method="spanMethod"
:cell-class-name="cellClassName"
>
...
javascript
复制代码
cellClassName({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
return "colorBox"; // 首列添加类名
}
},
css
复制代码
.el-table__body {
.el-table__row {
.el-table__cell {
background: #f7f7f7;
border-bottom: 1px solid #dcdcdc;
&.colorBox {
background: #acb2d9;
color: #32405b;
font-weight: bold;
border-bottom: 1px solid #32405b;
}
}
}
}
- 效果如图,会发现,动态赋予的 colorBox 类名,并没有被加到被合并的行的首列元素上
完整代码段
html
复制代码
<template>
<div class="tableBox">
<el-table
:data="tableData"
class="myTable"
header-row-class-name="tableHead"
:span-method="spanMethod"
:cell-class-name="cellClassName"
>
<el-table-column prop="date" label="日期"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="project" label="项目"> </el-table-column>
<el-table-column prop="address" label="地址" min-width="200">
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "dataList",
components: {},
data() {
return {
tableData: [],
};
},
mounted() {
this.getDataMock();
},
methods: {
getDataMock() {
for (var i = 0; i < 10; i++) {
let randomDay = Math.floor(Math.random() * 5 + 1);
this.tableData.push({
date: "2024-12-" + randomDay,
name: "王小虎" + i,
project: "项目" + i,
address: "上海市普陀区金沙江路 " + i + " 弄",
});
}
this.tableData.sort((a, b) => {
let time1 = new Date(a.date).getTime();
let time2 = new Date(b.date).getTime();
return time1 - time2;
});
},
cellClassName({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
return "colorBox";
}
},
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
// 只有第一列需要合并,所以限定为 columnIndex === 0
// 获取当前行的 rowspan
let rowspan = this.getTableDataSpan(this.tableData).spanData[rowIndex];
let colspan = rowspan === 0 ? 0 : 1; // 被合并到其他行,需要为 colspan 赋值为 0,否则为 1
return {
rowspan: rowspan,
colspan: colspan,
};
}
},
// 动态计算合并行的索引
getTableDataSpan(arr) {
let spanData = []; // 数据数组的 rowspan 集合
// rowspan > 1,合并行
// rowspan == 1,单独行,不参与合并
// rowspan == 0,被合并的行
let lastRowIndex = 0; // 记录索引
arr.forEach((item, index) => {
if (index == 0) {
// 第一行,默认认为不参与合并,记录为 1
spanData.push(1);
} else {
if (item.date == arr[index - 1].date) {
// 当前行的 date 与上一行的 date 相同,即当前行 的 rowspan 需要被记为 0
spanData.push(0);
// 向前找上次记录的索引,即需要当前行合并过去的目标行,使目标行的 rowspan 值加一
spanData[lastRowIndex] += 1;
} else {
// 当前行的 date 与上一行的 date 不相等,则当前行的 rowspan 记录为 1
spanData.push(1);
// 暂且记录一下 lastRowIndex
// 如果下一行与当前行的 date 值相同,就会合并到当前行,否则会更新 lastRowIndex 的值,进行下次对比
lastRowIndex = index;
}
}
});
return {
spanData: spanData,
lastRowIndex: lastRowIndex,
};
},
},
};
</script>
<style lang="less" scoped>
.tableBox {
background: #fff;
padding: 50px 0;
/deep/ .myTable {
width: 700px;
margin: 0 auto;
border-radius: 20px;
.tableHead {
.el-table__cell {
background-color: #bee7c5;
color: #264f30;
border-bottom: none;
&:first-child {
background: #435f5b;
color: #fff;
}
}
}
.el-table__body {
.el-table__row {
.el-table__cell {
background: #f7f7f7;
border-bottom: 1px solid #dcdcdc;
&.colorBox {
background: #acb2d9;
color: #32405b;
font-weight: bold;
border-bottom: 1px solid #32405b;
}
}
}
}
}
}
</style>