vue中树状结构转行数据,并渲染成table的方法

场景: 我们现在有一个树状结构的数据,如下图:
在这里插入图片描述
大概的数据结构如下:

const tree = {
	value: '根节点', children: [ { value: '学校', children: [ { value: '学生', children: [ { value: '年龄', children: [ { value: '身高' } ] } ] } ...... ] } ] } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

现在我们要将这样的数据转为行数据, 并用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' }], ...... ]; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
第二步,添加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 }], ...... ]; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

但是可以发现,我们需要的合并信息解析到了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 }], ...... ]; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
<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> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

大功告成!最后的效果如下:
在这里插入图片描述

猜你喜欢

转载自www.cnblogs.com/sexintercourse/p/13402206.html