效果图
{
name: '河南省',
children: [
{
name: '郑州市'
},
{
name: '商丘市'
},
{
name: '信阳市',
children: [
{
name: '淮滨县',
children: [
{
name: '王家岗乡'
}
]
},
{
name: '固始县'
}
]
}
]
},
{
name: '安徽省',
children: [
{
name: '阜阳市',
}
]
},
{
name: '上海市'
}
]
首先先获取数据的最长节点,用来判断合并单元格时应该合并几列
function getMaxNodeCount(tree, currentCount = 0) {
if (!tree || tree.length === 0) return currentCount;
let maxCount = 0;
for (const node of tree) {
// 当前节点算一个节点
const currentPathCount = currentCount + 1;
// 如果有子节点,继续递归
if (node.children && node.children.length > 0) {
const childMax = getMaxNodeCount(node.children, currentPathCount);
maxCount = Math.max(maxCount, childMax);
} else {
// 叶子节点,记录当前路径的节点数
maxCount = Math.max(maxCount, currentPathCount);
}
}
return maxCount;
}
const maxLength = getMaxNodeCount(treeData);
console.log("最大深度(节点数):", maxLength);
判断每个单元格应该合并几列
const configColSpan = (arr, index = 0) => {
arr.forEach(item => {
if (!item.children || !item.children.length) {
item.colSpan = maxLength - index
} else {
item.colSpan = 1
configColSpan(item.children, index + 1)
}
})
}
configColSpan(treeData)
接着判断每个单元格应该合并几行
const configRowSpan = (nodes) => {
var rowSpan = 0;
for (let n = 0; n < nodes.length; n++) {
if (nodes[n].children && nodes[n].children.length > 0) {
nodes[n].rowSpan = configRowSpan(nodes[n].children);
} else {
nodes[n].rowSpan = 1;
}
rowSpan += nodes[n].rowSpan;
nodes[n].index = n
}
return rowSpan;
}
configRowSpan(treeData)
最后将数据转换为二维数组
//处理树形结构为二维数组
let list = [[]]
const treeToArr = (tree, arr) => {
tree.forEach(item => {
arr[arr.length - 1].push(item)
if (!item.children || item.children.length == 0) {
arr.push([])
} else {
treeToArr(item.children, arr);
}
})
}
treeToArr(treeData, list);
const tableData = ref(list)
模板代码
<tr v-for="(item, index) in tableData">
<template v-for="(arr, i) in item" :key="i">
<td :colspan="arr.colSpan" :rowspan="arr.rowSpan">{{ arr.name }}</td>
</template>
</tr>
</table>