首页 > 解决方案 > Json 数据到 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>');

标签: javascriptarraysjsontreeview

解决方案


只需根据原始数组在树内找到路...

完整代码:

/*--------------------------------------------------------*\
|  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>')

在该算法中,对原表的每个元素进行解构赋值,如下:

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 方法的使用详见 mdn):
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. treeinitilial_tree, 正在构建的数组(由, 这里= =>空数组初始化[]),这个元素必须在每次迭代时返回

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

  3. idx: 数组中元素 (curr) 的索引(此处无用,替换为_

  4. Origin: 方法使用的原始表

算法:

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

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

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

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

因此有 2 个部分:

1-使用原点表从 X-1 到 Xn 元素

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()方法从顶部添加元素
/与该array.push()方法不同,最后输入的元素因此位于零位置,
这允许测试通过
(!!road[0].parentID)
,索引值始终为零。
...对于双感叹号看这里

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

2-在构建的树结构中找到元素X-1的路径

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: I use my sort of Whitesmiths style code formatting for years

for info, it's look like that:

├─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

推荐阅读