需求描述
- 樹結構表格
- 可展開摺疊,有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>