动态层级表格合并
之前写了两层和三层数据的表格合并,数据处理.这种事先确定了表格的层级
如果表格的层级在一定范围内不固定,就需要动态处理了,最近研究了下,把方法记录下来
代码githup地址: https://github.com/shengbid/vue3-vite-demo/tree/main/src/views/table/mutilSpanTable页面效果:


全部代码
<template>
<div style="margin-top: 20px">
<p>动态层级表格合并</p>
<div style="margin-bottom: 10px">
表格层级(2-5):
<a-input-number
:value="maxLevel"
:min="2"
:max="5"
style="width: 220px"
@change="changeLevel"
/>
</div>
<a-table
:columns="columns"
:data-source="tableData"
:pagination="false"
bordered
>
<template #bodyCell="{ column, text }">
<template v-if="column.dataIndex === 'name'">
<a href="javascript:;">{{ text }}</a>
</template>
</template>
</a-table>
</div>
</template>
<script>
import { ref } from "vue";
import { omit } from "lodash";
export default {
name: "mutilSpan",
setup() {
const maxLevel = ref(2);
const tableData = ref([]);
const treeData = ref([]);
const columns = [
{
title: "Name",
dataIndex: "name",
customCell: (record, index) => {
if (record.level < 2) return {};
return {
rowSpan: record.rowSpan1 ? record.rowSpan1 : 0,
};
},
},
{
title: "Age",
dataIndex: "age",
customCell: (record, index) => {
if (record.level < 3) return {};
return {
rowSpan: record.rowSpan2 ? record.rowSpan2 : 0,
};
},
},
{
title: "Home phone",
dataIndex: "tel",
customCell: (record, index) => {
if (record.level < 4) return {};
return {
rowSpan: record.rowSpan3 ? record.rowSpan3 : 0,
};
},
},
{
title: "Phone",
dataIndex: "phone",
customCell: (record, index) => {
if (record.level < 5) return {};
return {
rowSpan: record.rowSpan4 ? record.rowSpan4 : 0,
};
},
},
{
title: "Address",
dataIndex: "address",
},
];
// 获取表格children length
const getChildLength = (data, spanLengths = []) => {
let newLeg = 0;
data.forEach((item) => {
if (item.children && item.children.length) {
getChildLength(item.children, spanLengths);
} else {
newLeg++;
}
});
spanLengths.push(newLeg);
return spanLengths;
};
// 处理表格数据
const handleTable = (data, parentItem) => {
data.forEach((item, i) => {
if (item.children && item.children.length) {
item[`rowSpan${item.level}`] = getChildLength(item.children).reduce(
(pre, cur) => {
return pre + cur;
},
0
);
handleTable(
item.children,
i === 0
? {
...parentItem,
...omit(item, "children"),
}
: { ...omit(item, "children") }
);
} else {
if (i === 0) {
tableData.value.push({ ...parentItem, ...omit(item, "children") });
} else {
tableData.value.push(omit(item, "children"));
}
}
});
};
// 生成表格树形数据
const initTable = () => {
const render = (level, key) => {
let newLevel = level;
const arr = [];
// 两种情况都可满足
const random = Math.floor(Math.random() * 3); // 1.children可以为空
// const random = Math.ceil(Math.random() * 3); // 2.每层children下都有值
for (let i = 0; i < random; i++) {
const item = {
key: `${key}${i}`,
name: "John Brown",
age: 32,
tel: "0571-22098909",
phone: 18889898989,
address: "New York No. 1 Lake Park",
level: newLevel,
};
if (newLevel < maxLevel.value) {
item.children = render(newLevel + 1, item.key);
}
arr.push(item);
}
return arr;
};
treeData.value = render(1, "");
tableData.value = [];
handleTable(treeData.value);
};
initTable();
// console.log(treeData.value, tableData.value);
const changeLevel = (val) => {
maxLevel.value = val;
initTable();
console.log(treeData.value, tableData.value);
};
return {
maxLevel,
columns,
tableData,
changeLevel,
};
},
};
</script>
<style>
</style>
emplate 部分就是 ant design UI 的 table 组件引用
主要看下 js 部分
里面有三个方法
1. initTable 生成表格数据
这里一般是后端给的数据,这里是纯前端的,就自己生成了数据
数据格式为 [{xx: xxx, children: [{}]}]
这里注意,如果你们后端返回的数据,是这种父级字段与字级字段不一致, [{parentName: 1, children: [{name: 'xx'}]}]
你需要再写个方法,循环处理把上一级的数据放到下一级 [{parentName: 1, name: [{parentName: 1, name: 'xx'}]}]
每一级数据加上一个 level 字段,方便之后的操作
2. getChildLength 获取当前 item 下所有 children 的长度
表格合并,最重要的是要知道合并的行数,其实就是嵌套 children 的 length
所以用这个方法获取每一个有 children 的 item 的合并 length
3. handleTable 将表格处理成一维数组
表格渲染时,实际设计一条一条的数据,需要把初始的树形数据转变成一维数组
表格的数据长度是以这个树形数据最后一级的 children 个数决定的,所以这里是一个递归,直到最后一级时,把数据 push 到 tableData 里面
这里对于合并行的处理, 需要合并的数据行都放在 i=0 的那一行
举例: 原始数据如下
const initData = [ { key: "1", name: "John Brown", level: 1, children: [ { key: "10", name: "John Brown", level: 2, children: [ { key: "100", name: "John Brown", level: 3 }, ], }, { key: "11", name: "John Brown", level: 2, children: [ { key: "110", name: "John Brown", level: 3 }, { key: "111", name: "John Brown", level: 3 }, ], }, ], } ]
展示出来的效果应该是:
最外层的合并行应该是 3 行 也就是最后一层 children 的个数
第二层的合并行 是 1 行 和 2 行
处理好的 tableData 就是这样
[ { key: "100" name: "John Brown" rowSpan1: 3 rowSpan2: 1 level: 3 }, { key: "110" name: "John Brown" rowSpan2: 2 level: 3 } { key: "111" name: "John Brown" level: 3 } ]
对于 columns 的设置,根据 level 和`${rowSpan}{level}`来判断

浙公网安备 33010602011771号