需求描述
- 树结构表格
- 可展开折叠,有children子集项
- 并且对应列还需要合并单元格(大类合并)
- 笔者试了试 使用el-table自带的树结构表格似乎没法实现
- 就这个:
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
- 于是,只能换种思路实现了
- 添加行、删除行方式,同时动态计算需要合并的单元格信息
效果图
思路一:计算出现次数,并按照大类,给到对应单元格合并信息
完整代码,复制粘贴即用
<template>
<div>
<el-table ref="myTableRef" :data="tableData" border :span-method="arraySpanMethod">
<el-table-column prop="month" label="月份" width="72" />
<el-table-column prop="incomeType" label="收益类别" width="180">
<template slot-scope="scope">
<span class="arrow" v-if="scope.row.children" @click="handleExpand(scope)">
<span v-if="scope.row.expand">⬇️</span>
<span v-else>➡️</span>
</span>
<span :class="{ isChild: scope.row.level === 2 }">{{
scope.row.incomeType
}}</span>
</template>
</el-table-column>
<el-table-column prop="value" label="金额" width="180"> </el-table-column>
<el-table-column prop="unit" label="单位" width="180"> </el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
mergeInfo: {},
tableData: [
{
id: 1,
month: "三月",
incomeType: "工资",
unit: "元",
value: 2000,
level: 1,
},
{
id: 2,
month: "三月",
incomeType: "奖金",
unit: "元",
value: 500,
expand: false,
level: 1,
children: [
{
id: 21,
month: "三月",
incomeType: "个人奖金",
unit: "元",
value: 300,
level: 2,
},
{
id: 22,
month: "三月",
incomeType: "团队奖金",
unit: "元",
value: 200,
level: 2,
},
],
},
{
id: 3,
month: "三月",
incomeType: "外快",
unit: "元",
value: 80,
level: 1,
},
{
id: 4,
month: "四月",
incomeType: "奖金",
unit: "元",
value: 600,
expand: false,
level: 1,
children: [
{
id: 41,
month: "四月",
incomeType: "个人奖金",
unit: "元",
value: 300,
level: 2,
},
{
id: 42,
month: "四月",
incomeType: "团队奖金",
unit: "元",
value: 200,
level: 2,
},
{
id: 43,
month: "四月",
incomeType: "绩效奖金",
unit: "元",
value: 100,
level: 2,
},
],
},
{
id: 5,
month: "四月",
incomeType: "外快",
unit: "元",
value: 80,
level: 1,
},
{
id: 6,
month: "五月",
incomeType: "奖金",
unit: "元",
value: 600,
expand: false,
level: 1,
children: [
{
id: 61,
month: "五月",
incomeType: "个人奖金",
unit: "元",
value: 300,
level: 2,
},
{
id: 62,
month: "五月",
incomeType: "团队奖金",
unit: "元",
value: 200,
level: 2,
},
{
id: 63,
month: "五月",
incomeType: "绩效奖金",
unit: "元",
value: 100,
level: 2,
},
],
},
{
id: 7,
month: "五月",
incomeType: "外快",
unit: "元",
value: 80,
level: 1,
},
],
};
},
mounted() {
this.calCellMerge(this.tableData);
},
methods: {
handleExpand({ $index, row, column, $event }) {
row.expand = !row.expand;
if (row.expand) {
// 从索引处把子集的元素取出,添加进去(新增行)
this.tableData.splice($index + 1, 0, ...row.children);
} else {
// 从索引处把子集的元素直接去除(删除行)
this.tableData.splice($index + 1, row.children.length);
}
this.calCellMerge(this.tableData);
},
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
// 针对于月份列进行合并
if (column.label != "月份") return;
if (row.month == "三月") {
if (rowIndex == this.tableData.findIndex((item) => item.month == "三月")) {
// 头一个出现的往下走对应行数
return {
rowspan: this.mergeInfo["三月"],
colspan: 1,
};
} else {
// 剩下的直接 0 0 即去掉单元格
return {
rowspan: 0,
colspan: 0,
};
}
}
if (row.month == "四月") {
if (rowIndex == this.tableData.findIndex((item) => item.month == "四月")) {
return {
rowspan: this.mergeInfo["四月"],
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
if (row.month == "五月") {
if (rowIndex == this.tableData.findIndex((item) => item.month == "五月")) {
return {
rowspan: this.mergeInfo["五月"],
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
},
calCellMerge(tableData) {
// 统计月份出现的次数
let obj = {};
tableData.forEach((item) => {
if (!obj[item.month]) {
obj[item.month] = 1;
} else {
obj[item.month] = obj[item.month] + 1;
}
});
this.mergeInfo = obj;
},
},
};
</script>
<style>
.arrow {
cursor: pointer;
font-size: 16px;
}
.isChild {
padding-left: 20px;
}
</style>
思路二:把单元格合并信息,添加到tableData中的每一项中,直接使用
完整代码
<template>
<div>
<el-table ref="myTableRef" :data="tableData" border :span-method="arraySpanMethod">
<el-table-column prop="month" label="月份" width="72" />
<el-table-column prop="incomeType" label="收益类别" width="180">
<template slot-scope="scope">
<span class="arrow" v-if="scope.row.children" @click="handleExpand(scope.row)">
<span v-if="scope.row.expand">⬇️</span>
<span v-else>➡️</span>
</span>
<span :class="{ isChild: scope.row.level === 2 }">{{
scope.row.incomeType
}}</span>
</template>
</el-table-column>
<el-table-column prop="value" label="金额" width="180"> </el-table-column>
<el-table-column prop="unit" label="单位" width="180"> </el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
id: 1,
month: "三月",
incomeType: "工资",
unit: "元",
value: 2000,
level: 1,
},
{
id: 2,
month: "三月",
incomeType: "奖金",
unit: "元",
value: 500,
expand: false,
level: 1,
children: [
{
id: 21,
month: "三月",
incomeType: "个人奖金",
unit: "元",
value: 300,
level: 2,
},
{
id: 22,
month: "三月",
incomeType: "团队奖金",
unit: "元",
value: 200,
level: 2,
},
],
},
{
id: 3,
month: "三月",
incomeType: "外快",
unit: "元",
value: 80,
level: 1,
},
{
id: 5,
month: "四月",
incomeType: "奖金",
unit: "元",
value: 600,
expand: false,
level: 1,
children: [
{
id: 51,
month: "四月",
incomeType: "个人奖金",
unit: "元",
value: 300,
level: 2,
},
{
id: 52,
month: "四月",
incomeType: "团队奖金",
unit: "元",
value: 200,
level: 2,
},
{
id: 53,
month: "四月",
incomeType: "绩效奖金",
unit: "元",
value: 100,
level: 2,
},
],
},
{
id: 6,
month: "四月",
incomeType: "外快",
unit: "元",
value: 80,
level: 1,
},
{
id: 7,
month: "五月",
incomeType: "奖金",
unit: "元",
value: 600,
expand: false,
level: 1,
children: [
{
id: 71,
month: "五月",
incomeType: "个人奖金",
unit: "元",
value: 300,
level: 2,
},
{
id: 72,
month: "五月",
incomeType: "团队奖金",
unit: "元",
value: 200,
level: 2,
},
{
id: 73,
month: "五月",
incomeType: "绩效奖金",
unit: "元",
value: 100,
level: 2,
},
],
},
{
id: 8,
month: "五月",
incomeType: "外快",
unit: "元",
value: 80,
level: 1,
},
],
};
},
mounted() {
// 把合并信息设置到表格数据中
this.addMergeInfoInToTableItem(this.tableData);
},
methods: {
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
// 第0列,月份列进行控制
if ([0].includes(columnIndex)) {
return row.dateSpan;
}
},
addMergeInfoInToTableItem(datas = [], arraySpan = {}) {
// 遍历后,把合并信息添加到表格数据中
datas.forEach((it, idx) => {
it.idx = idx;
if (!arraySpan[it.month]) {
it.dateSpan = {
rowspan: 1,
colspan: 1,
};
arraySpan[it.month] = it;
} else if (arraySpan[it.month]) {
arraySpan[it.month].dateSpan.rowspan++;
it.dateSpan = {
rowspan: 0,
colspan: 0,
};
}
});
},
handleExpand(row) {
row.expand = !row.expand;
if (row.expand) {
this.tableData.splice(row.idx + 1, 0, ...row.children);
} else {
this.tableData.splice(row.idx + 1, row.children.length);
}
this.addMergeInfoInToTableItem(this.tableData);
this.reDraw();
},
// 重绘表格很有用
reDraw() {
this.$nextTick(() => {
this.$refs.myTableRef.doLayout();
});
},
},
};
</script>
<style>
.arrow {
cursor: pointer;
font-size: 16px;
}
.isChild {
padding-left: 20px;
}
</style>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。