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>

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM