JS構建一個樹形結構數據

昨天小組一成員跟一個萌新JAVA後端對接時,後端不會構建樹結構數據,要前端本身轉換,兩我的扯了半天,看不下去,寫了一個公共的方法來將有父子關係的數組轉換成樹形結構數據。前端

  • 數組:
[
   {
       id: 1,
       name: "1"
   },
   {
       id: 2,
       name: "1-1",
       pid: 1
   },
   {
       id: 3,
       name: "1-1-1",
       pid: 2
   },
   {
       id: 4,
       name: "1-2",
       pid: 1
   },
   {
       id: 5,
       name: "1-2-2",
       pid: 4
   },
   {
       id: 6,
       name: "1-1-1-1",
       pid: 3
   },
   {
       id: 7,
       name: "2"
   }
]
複製代碼

項目是用Vue開發,因此把方法添加到Vue的實例方法中後端

const install = function (Vue, opts) {
   /**
    * [deepClone 數組/對象深度拷貝]
    * @param  {[type]} source [數組/對象]
    * @return {[type]}        [description]
    */
   Vue.prototype.deepClone = function (source) {
       if (!source && typeof source !== 'object') {
           throw new Error('error arguments', 'shallowClone');
       }
       const targetObj = source.constructor === Array ? [] : {};
       for (const keys in source) {
           if (source.hasOwnProperty(keys)) {
               if (source[keys] && typeof source[keys] === 'object') {
                   targetObj[keys] = source[keys].constructor === Array ? [] : {};
                   targetObj[keys] = this.deepClone(source[keys]);
               } else {
                   targetObj[keys] = source[keys];
               }
           }
       }
       return targetObj;
   };
   /**
    * [structureTreeData 構建一個樹形結構數據]
    * @param  {[Array]} data [有父子關係的數組]
    * @param  {[String]} id  [節點ID]
    * @param  {[String]} pid [對應父節點ID]
    * @return {[Object]}     [樹形結構數據]
    */
   Vue.prototype.structureTreeData = function (data, id = "id", pid = "pid") {
       //沒有父節點的數據
       let parents = data.filter(
           value => value.pid == "undefined" || value.pid == null
       );

       //有父節點的數據
       let childrens = data.filter(
           value => value.pid !== "undefined" && value.pid != null
       );

       //構造樹形結構數據
       let structure = (parents, children) => {
           //遍歷父節點數據
           parents.forEach(parent => {
               //遍歷子節點數據
               childrens.forEach((children, index) => {
                   //此時找到父節點對應的一個子節點
                   if (children.pid === parent.id) {
                       //對子節點數據進行深拷貝
                       let newChildrens = this.deepClone(childrens);
                       //讓當前子節點從newChildrens中移除,newChildrens做爲新的子節點數據,
                       //這裏是爲了讓遞歸時,子節點的遍歷次數更少,若是父子關係的層級越多,越有利
                       newChildrens.splice(index, 1);
                       //讓當前子節點做爲惟一的父節點,去遞歸查找其對應的子節點
                       structure([children], newChildrens);
                       //把找到子節點放入父節點的children屬性中
                       typeof parent.children !== "undefined"
                           ? parent.children.push(children)
                           : (parent.children = [children]);
                   }
               });
           });
       };
       //調用構造方法
       structure(parents, childrens);
       return parents;
   };
}
export default {
   install
}
複製代碼
相關文章
相關標籤/搜索