vue中树状结构转行数据,并渲染成table的方法
这个算法非常有价值.50块钱提供核心协助
我qq
840189859
我微信
18500591275
场景: 我们现在有一个树状结构的数据,如下图:
大概的数据结构如下:
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>
大功告成!最后的效果如下:
漫思