vue中树状结构转行数据,并渲染成table的方法
场景: 我们现在有一个树状结构的数据,如下图:大概的数据结构如下:const tree = {value: '根节点',children: [{value: '学校',children: [{value: '学生',children: [...
·
场景: 我们现在有一个树状结构的数据,如下图:
大概的数据结构如下:
const tree = {
value: '根节点',
children: [
{
value: '学校',
children: [
{
value: '学生',
children: [
{
value: '年龄',
children: [
{
value: '身高'
}
]
}
]
}
......
]
}
]
}
现在我们要将这样的数据转为行数据, 并用vue将其渲染为table, 效果如下:
OK,下面我们一一进行解析。
第一步,递归树状结构,转化为行数据
parseTreeToRow(node, data = [], row = []) {
if (!node.children) {
data.push(row);
} else {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const cell = { value: child.value };
this.parseTreeToRow(child, data, [...row, cell]);
}
}
return data;
};
//通过上面的递归函数,解析出来的行数据如下:
const data = [
[{ value: '学校'}, { value: '学生' }, { value: '年龄' }, { value: '身高' }],
[{ value: '成都一中'}, { value: '张三' }, { value: '17' }, { value: '170' }],
[{ value: '成都二中'}, { value: '李四' }, { value: '17' }, { value: '174' }],
[{ value: '成都二中'}, { value: '王五' }, { value: '18' }, { value: '168' }],
[{ value: '成都二中'}, { value: '王五' }, { value: '19' }, { value: '177' }],
......
];
第二步,添加rowspan信息
此时,很明显渲染出来的table并没有进行合并,如果对解析后的行数据二次解析亦可找到其rowspan,这里不做二次解析,我们回到上面的递归函数中,做如下处理:
parseTreeToRow(node, data = [], row = []) {
if (!node.children) {
data.push(row);
} else {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const cell = {
value: child.value,
rowspan: this.computeLeafCount(node)
};
this.parseTreeToRow(child, data, [...row, cell]);
}
}
return data;
};
/**
1. 计算某个节点下叶子节点的数量
2. @param { Object } node 节点
3. @returns { Number } leafCount 叶子节点的数量
*/
computeLeafCount(node) {
if(!node.children){
node.rowspan = 1;
return 1;
} else {
let leafCount = 0;
for(let i = 0 ; i < node.children.length ; i++) {
leafCount = leafCount + this.computeLeafCount(node.children[i]);
}
node.rowspan = leafCount;
return leafCount;
}
}
//解析出的数据如下:
const data = [
[{ value: '学校', rowspan: 7 }, { value: '学生', rowspan: 1 }, { value: '年龄', rowspan: 1 }, { value: '身高', rowspan: 1 }],
[{ value: '成都一中', rowspan: 7 }, { value: '张三', rowspan: 1 }, { value: '17', rowspan: 1 }, { value: '170', rowspan: 1 }],
[{ value: '成都二中', rowspan: 7 }, { value: '李四', rowspan: 3 }, { value: '17', rowspan: 1 }, { value: '174', rowspan: 1 }],
[{ value: '成都二中', rowspan: 7 }, { value: '王五', rowspan: 3 }, { value: '18', rowspan: 1 }, { value: '168', rowspan: 1 }],
[{ value: '成都二中', rowspan: 7 }, { value: '王五', rowspan: 3 }, { value: '19', rowspan: 1 }, { value: '177', rowspan: 1 }],
......
];
但是可以发现,我们需要的合并信息解析到了child中,且相同的单元格只有第一行的rowspan保留,其余要置为0,。
第三步,处理异常合并信息
回到递归函数中,
parseTreeToRow(node, data = [], row = []) {
if (!node.children) {
data.push(row);
} else {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const cell = { value: child.value };
/******************添加的代码******************/
//深度克隆父亲,因为后代共用了该引用数据
const extendRow = [ ...JSON.parse(JSON.stringify(row)), cell];
if (extendRow.length === 1) { //第一列
extendRow[0].rowspan = 1;
} else if (extendRow.length > 1) {
//将该行的最后一列的rowspan赋给上一列
//再将自身置为1(避免最后一列无值)
extendRow[extendRow.length - 2].rowspan = i === 0 ? this.computeLeafCount(node) : 0;
extendRow[extendRow.length - 1].rowspan = 1;
}
/******************添加的代码******************/
this.parseTreeToRow(child, data, extendRow);
}
}
return data;
};
//解析后的数据结构如下:
const data = [
[{ value: '学校', rowspan: 1 }, { value: '学生', rowspan: 1 }, { value: '年龄', rowspan: 1 }, { value: '身高', rowspan: 1 }],
[{ value: '成都一中', rowspan: 1 }, { value: '张三', rowspan: 1 }, { value: '17', rowspan: 1 }, { value: '170', rowspan: 1 }],
[{ value: '成都二中', rowspan: 1 }, { value: '李四', rowspan: 3 }, { value: '17', rowspan: 1 }, { value: '174', rowspan: 1 }],
[{ value: '成都二中', rowspan: 1 }, { value: '王五', rowspan: 0 }, { value: '18', rowspan: 1 }, { value: '168', rowspan: 1 }],
[{ value: '成都二中', rowspan: 1 }, { value: '王五', rowspan: 0 }, { value: '19', rowspan: 1 }, { value: '177', rowspan: 1 }],
......
];
<table>
<tr v-for="(row, i) in data" :key="i">
<td
v-for="(cell, j) in row"
v-if="cell.rowspan"
:key="j"
:rowspan="cell.rowspan"
:colspan="cell.colspan">
<div class="cell">{{ cell.value }}</div>
</td>
</tr>
</table>
大功告成!最后的效果如下:
更多推荐
已为社区贡献3条内容
所有评论(0)