渲染出一棵树

时间:2015-11-07 23:02:29

标签: javascript

我需要在javascript中将平面数据与关系渲染成html树结构。我需要在没有任何图书馆帮助的情况下完成。数据本身是平的:

[
{id : 1, title : one, parent : null},
{id : 2, title : two, parent : 1},
{id : 3, title : three, parent : 2},
{id : 4, title : four, parent : null},
{id : 5, title : five, parent : 4},
{id : 6, title : six, parent : 4},
{id : 7, title : seven, parent : 6},
{id : 8, title : eight, parent : 7},
{id : 9, title : nine, parent : 8}
]

这是理想的结果:

<div>one
  <div>two
    <div>three</div>
  </div>
</div>
<div>four
  <div>five</div>
  <div>six
    <div>seven
      <div>eight
        <div>nine
        </div>
      </div>
    </div>
  </div>
</div>

数据的深度是任意的(即根据数据,它可以是一个或一百个深度)。

我一直在寻找答案,但大多数都指向库或使用本身嵌套的数据(在大多数情况下只会将嵌套问题推到服务器上)。

2 个答案:

答案 0 :(得分:1)

成本为O(n)的迭代方法是

function makeTree(data) {
  var elements = Array(data.length + 1),
      proto = document.createElement('div');
  for(var i=0; i<=data.length; ++i)
    elements[i] = proto.cloneNode(false);
  for(var i=0; i<data.length; ++i) {
    var elem = elements[data[i].id];
    elements[+data[i].parent].appendChild(elem);
    elem.insertBefore(
      document.createTextNode(data[i].title),
      elem.firstChild
    );
  }
  return elements[0];
}

&#13;
&#13;
var data = [
  {id : 9, title : "nine", parent : 8},
  {id : 1, title : "one", parent : null},
  {id : 2, title : "two", parent : 1},
  {id : 3, title : "three", parent : 2},
  {id : 4, title : "four", parent : null},
  {id : 5, title : "five", parent : 4},
  {id : 6, title : "six", parent : 4},
  {id : 7, title : "seven", parent : 6},
  {id : 8, title : "eight", parent : 7}
];
function makeTree(data) {
  var elements = Array(data.length + 1),
      proto = document.createElement('div');
  for(var i=0; i<=data.length; ++i)
    elements[i] = proto.cloneNode(false);
  for(var i=0; i<data.length; ++i) {
    var elem = elements[data[i].id];
    elements[+data[i].parent].appendChild(elem);
    elem.insertBefore(
      document.createTextNode(data[i].title),
      elem.firstChild
    );
  }
  return elements[0];
}
document.body.appendChild(makeTree(data));
&#13;
div {
  padding-left: 10px;
}
&#13;
&#13;
&#13;

即使您在定义数据之前将元素作为父元素引用,上述代码仍然有效。但是,它假定ID是从1到n的连续整数。如果它们可以是稀疏的或字符串,则使用对象而不是数组。平均而言,它也将是O(n)。

&#13;
&#13;
var data = [
  {id : "id9", title : "nine", parent : "id8"},
  {id : "id1", title : "one", parent : null},
  {id : "id2", title : "two", parent : "id1"},
  {id : "id3", title : "three", parent : "id2"},
  {id : "id4", title : "four", parent : null},
  {id : "id5", title : "five", parent : "id4"},
  {id : "id6", title : "six", parent : "id4"},
  {id : "id7", title : "seven", parent : "id6"},
  {id : "id8", title : "eight", parent : "id7"}
];
function makeTree(data) {
  function getEl(id) {
    if(id === null) return wrapper;
    return elements[id] = elements[id] || wrapper.cloneNode(false);
  }
  var elements = {},
      wrapper = document.createElement('div');
  for(var i=0; i<data.length; ++i) {
    var el = getEl(data[i].id);
    getEl(data[i].parent).appendChild(el);
    el.insertBefore(
      document.createTextNode(data[i].title),
      el.firstChild
    );
  }
  return wrapper;
}
document.body.appendChild(makeTree(data));
&#13;
div {
  padding-left: 10px;
}
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这是一个递归函数,用于将对象数组(包含您的结构)转换为div字符串,表示function menuTree(nodes, parentId) { return nodes.reduce(function(html, node) { return html + (node.parent === parentId ? '\n<div>' + node.title + menuTree(nodes, node.id) + '</div>' : ''); }, ''); } 标记的层次结构。

var nodes = [
    {"id": 1, "title": "one",   "parent": null},
    {"id": 2, "title": "two",   "parent": 1},
    {"id": 3, "title": "three", "parent": 2},
    {"id": 4, "title": "four",  "parent": null},
    {"id": 5, "title": "five",  "parent": 4},
    {"id": 6, "title": "six",   "parent": 4},
    {"id": 7, "title": "seven", "parent": 6},
    {"id": 8, "title": "eight", "parent": 7},
    {"id": 9, "title": "nine",  "parent": 8}
];
var html = menuTree(nodes, null);
console.log(html);

你这样称呼它:

json

以下是fiddle以交互方式演示上述内容。这个小提琴允许您更改div描述并相应地重现css树。通过使用一些基本div [self.textView becomeFirstResponder]; [self.textView resignFirstResponder]; 树将使用缩进进行渲染。