Json 数据到 javaScript 树视图

Json data to javaScript Treeview

您好,有一个json数据如下。

    var arr = [{
                "ID": 1,
                "parentID": 0,
                "Phone": "(403) 125-2552",
                "City": "Coevorden",
                "Name": "Grady"
            }, {
                "ID": 2,
                "parentID": 0,
                "Phone": "(979) 486-1932",
                "City": "Chełm",
                "Name": "Scarlet"
            }, {
                "ID": 3,
                "parentID": 0,
                "Phone": "(573) 685-8350",
                "City": "Wardha",
                "Name": "Adria"
            }, {
                "ID": 4,
                "parentID": 3,
                "Phone": "(630) 292-9737",
                "City": "Villers-la-Loue",
                "Name": "Xerxes"
            }, {
                "ID": 5,
                "parentID": 0,
                "Phone": "(755) 968-6539",
                "City": "Gönen",
                "Name": "Madeson"
            }, {
                "ID": 6,
                "parentID": 5,
                "Phone": "(644) 892-5485",
                "City": "Timkur",
                "Name": "Rae"
            }, {
                "ID": 7,
                "parentID": 0,
                "Phone": "(896) 297-6568",
                "City": "Louvain-la-Neuve",
                "Name": "Celeste"
            }, {
                "ID": 8,
                "parentID": 5,
                "Phone": "(168) 452-3538",
                "City": "Worksop",
                "Name": "Rowan"
            }, {
                "ID": 9,
                "parentID": 5,
                "Phone": "(873) 337-9560",
                "City": "Bad Neuenahr-Ahrweiler",
                "Name": "Kendall"
            }, {
                "ID": 10,
                "parentID": 0,
                "Phone": "(450) 579-0491",
                "City": "MIDdelburg",
                "Name": "Madaline"
            }, {
                "ID": 11,
                "parentID": 0,
                "Phone": "(111) 162-2502",
                "City": "Birecik",
                "Name": "Chandler"
            }, {
                "ID": 12,
                "parentID": 8,
                "Phone": "(712) 483-3905",
                "City": "Courbevoie",
                "Name": "Craig"
            }, {
                "ID": 13,
                "parentID": 8,
                "Phone": "(872) 499-5833",
                "City": "Cuccaro Vetere",
                "Name": "Basia"
            }, {
                "ID": 14,
                "parentID": 6,
                "Phone": "(724) 797-0077",
                "City": "Portree",
                "Name": "Elmo"
            }, {
                "ID": 15,
                "parentID": 5,
                "Phone": "(366) 967-0433",
                "City": "Dublin",
                "Name": "Cairo"
            }, {
                "ID": 16,
                "parentID": 11,
                "Phone": "(147) 708-7321",
                "City": "Rivière-du-Loup",
                "Name": "Mannix"
            }, {
                "ID": 17,
                "parentID": 0,
                "Phone": "(407) 519-9894",
                "City": "Roubaix",
                "Name": "Justine"
            }]
.
.
.

我想制作此数据的树状视图,得到如下所示的结果。没问题,正常使用。

[
    {
        "ID": 1,
        "parentID": 0,
        "Phone": "(403) 125-2552",
        "City": "Coevorden",
        "Name": "Grady"
    },
    {
        "ID": 2,
        "parentID": 0,
        "Phone": "(979) 486-1932",
        "City": "Chełm",
        "Name": "Scarlet",
        "children": [
            {
                "ID": 30,
                "parentID": 2,
                "Phone": "(641) 756-7073",
                "City": "Harrison Hot Springs",
                "Name": "Hamilton",
                "children": [
                    {
                        "ID": 54,
                        "parentID": 30,
                        "Phone": "(800) 876-5942",
                        "City": "Ribnitz-Damgarten",
                        "Name": "Kelsie",
                        "children": [
                            {
                                "ID": 62,
                                "parentID": 54,
                                "Phone": "(523) 159-2911",
                                "City": "Biała Podlaska",
                                "Name": "Clio"
                            }
                        ]
                    },
                    {
                        "ID": 87,
                        "parentID": 30,
                        "Phone": "(500) 895-9220",
                        "City": "Piracicaba",
                        "Name": "Maya"
                    }
                ]
            },
            {
                "ID": 40,
                "parentID": 2,
                "Phone": "(921) 336-7339",
                "City": "Namur",
                "Name": "Lionel"
            },
            {
                "ID": 43,
                "parentID": 2,
                "Phone": "(410) 695-8540",
                "City": "Saint-Laurent",
                "Name": "Deanna",
                "children": [
                    {
                        "ID": 63,
                        "parentID": 43,
                        "Phone": "(475) 190-5102",
                        "City": "Nicoya",
                        "Name": "Nola"
                    },
                    {
                        "ID": 98,
                        "parentID": 43,
                        "Phone": "(268) 572-5059",
                        "City": "San Marcello Pistoiese",
                        "Name": "Marny"
                    }
                ]
            }
        ]
    },
    {
        "ID": 3,
        "parentID": 0,
        "Phone": "(573) 685-8350",
        "City": "Wardha",
        "Name": "Adria",
        "children": [
            {
                "ID": 4,
                "parentID": 3,
                "Phone": "(630) 292-9737",
                "City": "Villers-la-Loue",
                "Name": "Xerxes",
                "children": [
                    {
                        "ID": 44,
                        "parentID": 4,
                        "Phone": "(287) 866-8953",
                        "City": "Fiuminata",
                        "Name": "Darius",
                        "children": [
                            {
                                "ID": 47,
                                "parentID": 44,
                                "Phone": "(779) 411-0381",
                                "City": "Pontedera",
                                "Name": "Harding",
                                "children": [
                                    {
                                        "ID": 92,
                                        "parentID": 47,
                                        "Phone": "(925) 263-0254",
                                        "City": "Curacaví",
                                        "Name": "Aristotle"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "ID": 56,
                        "parentID": 4,
                        "Phone": "(963) 719-2718",
                        "City": "Gore",
                        "Name": "Rafael"
                    }
                ]
            },
            {
                "ID": 58,
                "parentID": 3,
                "Phone": "(464) 318-7548",
                "City": "Curepto",
                "Name": "Leila"
            }
        ]
    .
    .
    .

我的主要问题是 parentID:我不想将 parentID 写入写入 0 的对象。但是当我删除 parentID: 0 的地方时,它无法正常工作。你能帮忙吗?

我运行的代码是:

tree = function(array) {
        var o = {
            ID: 0
        }

        function arrGet(o) {
            if (Array.isArray(o.children)) {
                o.children.forEach(arrGet);
            }
        }
        array.forEach(function(a) {
            o[a.ID] = o[a.ID] || {
                ID: a.ID,
                parentID: a.parentID,
                Phone: a.Phone,
                City: a.City,
                Name: a.Name
            };
            a.children = o[a.ID].children;
            o[a.parentID] = o[a.parentID] || {
                ID: a.parentID
            };
            o[a.parentID].children = o[a.parentID].children || [];
            o[a.parentID].children.push(o[a.ID]);
        });
        arrGet(o[0]);
        return o[0].children;
    }(arr);
document.writeln('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');

你可以做的是在 parentID 等于 0 时使用 delete 运算符。这将从对象中删除 属性,因此不会显示它。

var arr = [{
                "ID": 1,
                "parentID": 0,
                "Phone": "(403) 125-2552",
                "City": "Coevorden",
                "Name": "Grady"
            }, {
                "ID": 2,
                "parentID": 0,
                "Phone": "(979) 486-1932",
                "City": "Chełm",
                "Name": "Scarlet"
            }, {
                "ID": 3,
                "parentID": 0,
                "Phone": "(573) 685-8350",
                "City": "Wardha",
                "Name": "Adria"
            }, {
                "ID": 4,
                "parentID": 3,
                "Phone": "(630) 292-9737",
                "City": "Villers-la-Loue",
                "Name": "Xerxes"
            }, {
                "ID": 5,
                "parentID": 0,
                "Phone": "(755) 968-6539",
                "City": "Gönen",
                "Name": "Madeson"
            }, {
                "ID": 6,
                "parentID": 5,
                "Phone": "(644) 892-5485",
                "City": "Timkur",
                "Name": "Rae"
            }, {
                "ID": 7,
                "parentID": 0,
                "Phone": "(896) 297-6568",
                "City": "Louvain-la-Neuve",
                "Name": "Celeste"
            }, {
                "ID": 8,
                "parentID": 5,
                "Phone": "(168) 452-3538",
                "City": "Worksop",
                "Name": "Rowan"
            }, {
                "ID": 9,
                "parentID": 5,
                "Phone": "(873) 337-9560",
                "City": "Bad Neuenahr-Ahrweiler",
                "Name": "Kendall"
            }, {
                "ID": 10,
                "parentID": 0,
                "Phone": "(450) 579-0491",
                "City": "MIDdelburg",
                "Name": "Madaline"
            }, {
                "ID": 11,
                "parentID": 0,
                "Phone": "(111) 162-2502",
                "City": "Birecik",
                "Name": "Chandler"
            }, {
                "ID": 12,
                "parentID": 8,
                "Phone": "(712) 483-3905",
                "City": "Courbevoie",
                "Name": "Craig"
            }, {
                "ID": 13,
                "parentID": 8,
                "Phone": "(872) 499-5833",
                "City": "Cuccaro Vetere",
                "Name": "Basia"
            }, {
                "ID": 14,
                "parentID": 6,
                "Phone": "(724) 797-0077",
                "City": "Portree",
                "Name": "Elmo"
            }, {
                "ID": 15,
                "parentID": 5,
                "Phone": "(366) 967-0433",
                "City": "Dublin",
                "Name": "Cairo"
            }, {
                "ID": 16,
                "parentID": 11,
                "Phone": "(147) 708-7321",
                "City": "Rivière-du-Loup",
                "Name": "Mannix"
            }, {
                "ID": 17,
                "parentID": 0,
                "Phone": "(407) 519-9894",
                "City": "Roubaix",
                "Name": "Justine"
            }];
            
tree = function(array) {
        var o = {
            ID: 0
        }

        function arrGet(o) {
            if (Array.isArray(o.children)) {
                o.children.forEach(arrGet);
            }
        }
        array.forEach(function(a) {

            o[a.ID] = o[a.ID] || {
                ID: a.ID,
                parentID: a.parentID,
                Phone: a.Phone,
                City: a.City,
                Name: a.Name
            };
            
            if(a.parentID === 0) 
              delete o[a.ID].parentID;
              
            a.children = o[a.ID].children;
            o[a.parentID] = o[a.parentID] || {
                ID: a.parentID
            };
            o[a.parentID].children = o[a.parentID].children || [];
            o[a.parentID].children.push(o[a.ID]);
        });
        arrGet(o[0]);
        return o[0].children;
    }(arr);
document.writeln('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');

var arr = [{
        "ID": 1,
        "Phone": "(403) 125-2552",
        "City": "Coevorden",
        "Name": "Grady"
    }, {
        "ID": 2,
        "Phone": "(979) 486-1932",
        "City": "Chełm",
        "Name": "Scarlet"
    }, {
        "ID": 3,
        "Phone": "(573) 685-8350",
        "City": "Wardha",
        "Name": "Adria"
    }, {
        "ID": 4,
        "parentID": 3,
        "Phone": "(630) 292-9737",
        "City": "Villers-la-Loue",
        "Name": "Xerxes"
    }, {
        "ID": 5,
        "Phone": "(755) 968-6539",
        "City": "Gönen",
        "Name": "Madeson"
    }, {
        "ID": 6,
        "parentID": 5,
        "Phone": "(644) 892-5485",
        "City": "Timkur",
        "Name": "Rae"
    }, {
        "ID": 7,
        "Phone": "(896) 297-6568",
        "City": "Louvain-la-Neuve",
        "Name": "Celeste"
    }, {
        "ID": 8,
        "parentID": 5,
        "Phone": "(168) 452-3538",
        "City": "Worksop",
        "Name": "Rowan"
    }, {
        "ID": 9,
        "parentID": 5,
        "Phone": "(873) 337-9560",
        "City": "Bad Neuenahr-Ahrweiler",
        "Name": "Kendall"
    }, {
        "ID": 10,
        "Phone": "(450) 579-0491",
        "City": "MIDdelburg",
        "Name": "Madaline"
    }, {
        "ID": 11,
        "Phone": "(111) 162-2502",
        "City": "Birecik",
        "Name": "Chandler"
    }, {
        "ID": 12,
        "parentID": 8,
        "Phone": "(712) 483-3905",
        "City": "Courbevoie",
        "Name": "Craig"
    }, {
        "ID": 13,
        "parentID": 8,
        "Phone": "(872) 499-5833",
        "City": "Cuccaro Vetere",
        "Name": "Basia"
    }, {
        "ID": 14,
        "parentID": 6,
        "Phone": "(724) 797-0077",
        "City": "Portree",
        "Name": "Elmo"
    }, {
        "ID": 15,
        "parentID": 5,
        "Phone": "(366) 967-0433",
        "City": "Dublin",
        "Name": "Cairo"
    }, {
        "ID": 16,
        "parentID": 11,
        "Phone": "(147) 708-7321",
        "City": "Rivière-du-Loup",
        "Name": "Mannix"
    }, {
        "ID": 17,
        "Phone": "(407) 519-9894",
        "City": "Roubaix",
        "Name": "Justine"
    }, {
        "ID": 18,
        "parentID": 14,
        "Phone": "(938) 793-5446",
        "City": "Eugene",
        "Name": "Dahlia"
    }, {
        "ID": 19,
        "parentID": 5,
        "Phone": "(425) 682-2189",
        "City": "Salisbury",
        "Name": "Irene"
    }, {
        "ID": 20,
        "parentID": 12,
        "Phone": "(351) 187-8200",
        "City": "Garaguso",
        "Name": "Trevor"
    }, {
        "ID": 21,
        "Phone": "(601) 944-5214",
        "City": "Pointe-au-Pic",
        "Name": "Iris"
    }, {
        "ID": 22,
        "parentID": 20,
        "Phone": "(479) 532-6127",
        "City": "Salt Lake City",
        "Name": "Fleur"
    }, {
        "ID": 23,
        "parentID": 19,
        "Phone": "(339) 973-1695",
        "City": "Meldert",
        "Name": "Hayley"
    }, {
        "ID": 24,
        "parentID": 11,
        "Phone": "(946) 766-1649",
        "City": "Corral",
        "Name": "Baker"
    }, {
        "ID": 25,
        "Phone": "(964) 413-7033",
        "City": "Joliet",
        "Name": "Leo"
    }, {
        "ID": 26,
        "parentID": 7,
        "Phone": "(898) 476-0059",
        "City": "Burntisland",
        "Name": "Rigel"
    }]

像这样的原始数据

根据原点数组找到树里面的路...

完整代码:

/*--------------------------------------------------------*\
|  treeMaker  : JSON [Array of obj] to Treeview (function) |
|                                                          |
|   input array objets must be like { ID,[ parentID ] ...} |
\* -------------------------------------------------------*/

const treeMaker = arr =>
  arr.reduce((tree,{parentID,...useful},_,Origin)=>
  {
  if (!parentID) tree.push({...useful})                          // direct case!
  else
    {
    let path = { children: tree }                             // path for insert
      , road = [ Origin.find(x=>x.ID===parentID) ]      // every road has an end
      ;
    while(!!road[0].parentID)            // as long as a parentID property exist
      {
      road.unshift(Origin.find(x=>x.ID===road[0].parentID))   // get road origin
      }
    for(let way of road)                  // make your way by following the road
      {
      path = path.children.find(x=>x.ID===way.ID) // change the path to children
      }
    if (!path.children) path.children = []   // if not exist, add children array
      ;
    path.children.push({...useful})                     // copy all useful items
    }
  return tree                                              // back to the trees!
  },[])
  
/*--------------------------------------------------------*/

// test part
const myArr = 
    [ { ID:  1,               Phone: '(403) 125-2552', City: 'Coevorden',              Name: 'Grady'    } 
    , { ID:  2,               Phone: '(979) 486-1932', City: 'Chełm',                  Name: 'Scarlet'  } 
    , { ID:  3,               Phone: '(573) 685-8350', City: 'Wardha',                 Name: 'Adria'    } 
    , { ID:  4, parentID:  3, Phone: '(630) 292-9737', City: 'Villers-la-Loue',        Name: 'Xerxes'   } 
    , { ID:  5,               Phone: '(755) 968-6539', City: 'Gönen',                  Name: 'Madeson'  } 
    , { ID:  6, parentID:  5, Phone: '(644) 892-5485', City: 'Timkur',                 Name: 'Rae'      } 
    , { ID:  7,               Phone: '(896) 297-6568', City: 'Louvain-la-Neuve',       Name: 'Celeste'  } 
    , { ID:  8, parentID:  5, Phone: '(168) 452-3538', City: 'Worksop',                Name: 'Rowan'    } 
    , { ID:  9, parentID:  5, Phone: '(873) 337-9560', City: 'Bad Neuenahr-Ahrweiler', Name: 'Kendall'  } 
    , { ID: 10,               Phone: '(450) 579-0491', City: 'MIDdelburg',             Name: 'Madaline' } 
    , { ID: 11,               Phone: '(111) 162-2502', City: 'Birecik',                Name: 'Chandler' } 
    , { ID: 12, parentID:  8, Phone: '(712) 483-3905', City: 'Courbevoie',             Name: 'Craig'    } 
    , { ID: 13, parentID:  8, Phone: '(872) 499-5833', City: 'Cuccaro Vetere',         Name: 'Basia'    } 
    , { ID: 14, parentID:  6, Phone: '(724) 797-0077', City: 'Portree',                Name: 'Elmo'     } 
    , { ID: 15, parentID:  5, Phone: '(366) 967-0433', City: 'Dublin',                 Name: 'Cairo'    } 
    , { ID: 16, parentID: 11, Phone: '(147) 708-7321', City: 'Rivière-du-Loup',        Name: 'Mannix'   } 
    , { ID: 17,               Phone: '(407) 519-9894', City: 'Roubaix',                Name: 'Justine'  } 
    , { ID: 18, parentID: 14, Phone: '(938) 793-5446', City: 'Eugene',                 Name: 'Dahlia'   } 
    , { ID: 19, parentID:  5, Phone: '(425) 682-2189', City: 'Salisbury',              Name: 'Irene'    } 
    , { ID: 20, parentID: 12, Phone: '(351) 187-8200', City: 'Garaguso',               Name: 'Trevor'   } 
    , { ID: 21,               Phone: '(601) 944-5214', City: 'Pointe-au-Pic',          Name: 'Iris'     } 
    , { ID: 22, parentID: 20, Phone: '(479) 532-6127', City: 'Salt Lake City',         Name: 'Fleur'    } 
    , { ID: 23, parentID: 19, Phone: '(339) 973-1695', City: 'Meldert',                Name: 'Hayley'   } 
    , { ID: 24, parentID: 11, Phone: '(946) 766-1649', City: 'Corral',                 Name: 'Baker'    } 
    , { ID: 25,               Phone: '(964) 413-7033', City: 'Joliet',                 Name: 'Leo'      } 
    , { ID: 26, parentID:  7, Phone: '(898) 476-0059', City: 'Burntisland',            Name: 'Rigel'    } 
    ] 

const myTree = treeMaker ( myArr )

document.write('<pre>myTree:\n')
document.write(JSON.stringify(myTree,0,2))
document.write('</pre>')

在这个算法中,destructuring assignment被用在了原来table的每个元素上,如下:

let element1 = { ID:6, parentID:5, City:'Timkur', Name:'Rae' }

let {parentID, ...useful} = element1 // destructuring assignment

console.log( parentID ) // return 5
console.log( useful )  // return  object { ID:6, City:'Timkur', Name:'Rae' }

console.log ( !parentID ) // return false

没有parentID 属性:

let element2 = { ID:7, City:'Louvain-la-Neuve', Name: 'Celeste' }

let {parentID, ...useful} = element2   // destructuring assignment

console.log( parentID ) // undefined
console.log( useful )  // return  object { ID:7, ....

console.log ( !parentID ) // return true

在这段代码中,解构赋值直接在数组方法的参数列表中使用reduce(进一步查看)

关于Array.reduce方法的使用(see mdn for more details):
const arr_tree = arr.reduce(function(tree,curr,idx,Origin) {…}, initilial_tree);
与箭头符号相同:
a) const arr_tree = arr.reduce((tree,curr,_,Origin)=>{…}, []);
b) const arr_tree = arr.reduce((tree,{parentID,...useful},_,Origin)=>

参数:

  1. tree,构造中的数组(由initilial_tree初始化,此处=[] =>空数组),每次迭代都必须返回此元素

  2. curr:当前元素(如在数组的循环中),**用于解构赋值
    {parentID,...有用} = curr(请比较 a)b) )

  3. idx:元素(curr)在数组上的索引(这里没用,用_代替)

  4. Origin:方法

    使用的原table

the algorithm:

对于具有 parentID 的任何元素,其 parent 必须在正在构建的树中找到。

也就是说,对于具有 parentID 的 X 元素,存在具有该 ID 的 X-1 元素。 如果这个 X-1 元素本身有一个 ParentID,那么还有另一个具有这个 ID 的 X-2 元素。 依此类推,直到我们找到一个 X-n 没有 ParentID 的元素。

这个 X-N 元素直接位于结果数组的根部。

剩下的就是按照正在构建的树结构中的反向路径: 我们在其根级寻找位置 Xn,然后在其 children 中寻找元素 X- (n-1),直到找到我们可以添加元素 X 的元素 X-1 的位置在其 children 的列表中。 如果 X-1 还没有 children,请确保添加一个空列表 children。

因此有两部分:

1- go up the road from X-1 to the X-n elements using the origin table

let road = [ Origin.find(x=>x.ID===parentID) ]      // every road has an end

while(!!road[0].parentID)             // as long as a parentID property exist
  {
  road.unshift(Origin.find(x=>x.ID===road[0].parentID))    // get road origin
  } 

如果我们从元素 X = { ID: 12, parentID: 8, ... Name: 'Craig'} 开始(其中 parentID 值为 8) 结果是:

road = [ { ID: 5, ...             Name: 'Madeson' }
       , { ID: 8, parentID: 5,... Name: 'Rowan'   }
       ]

注1:
使用array.unshift()方法从top
开始添加元素 / 与 array.push() 方法不同,最后输入的元素位于零位置,
允许测试通过
(!!road[0].parentID)
索引值始终为零。
...对于双感叹号look here

注2:
道路数组仅包含指向原始数组 objects 的“指针”。

2- find the path of element X-1 in tree structure under construction

let path = { children: tree }                             // path for insert

for(let way of road)                  // make your way by following the road
  {
  path = path.children.find(x=>x.ID===way.ID) // change the path to children
  }

note X: 我使用我的 Whitesmiths style code formatting 多年

有关信息,它看起来像这样:

├─1_Grady     
├─2_Scarlet   
├─3_Adria─┐    
│         └─4_Xerxes
├─5_Madeson─┐  
│           ├─6_Rae─┐      
│           │       └─14_Elmo─┐     
│           │                 └─18_Dahlia
│           ├─8_Rowan─┐    
│           │         ├─12_Craig─┐    
│           │         │          └─20_Trevor─┐   
│           │         │                      └─22_Fleur
│           │         └─13_Basia
│           ├─9_Kendall   
│           ├─15_Cairo     
│           └─19_Irene─┐    
│                      └─23_Hayley
├─7_Celeste─┐  
│           └─26_Rigel
├─10_Madaline  
├─11_Chandler─┐ 
│             ├─16_Mannix    
│             └─24_Baker
├─17_Justine   
├─21_Iris      
└─25_Leo