函数中的递归创建DOM树

时间:2014-11-15 00:00:49

标签: javascript dom recursion

好人,请向我解释,请使用此功能:

function createTreeDom(obj) {
  if (isObjectEmpty(obj)) return;

  var ul = document.createElement('ul');

  for (var key in obj) {
    var li = document.createElement('li');
    li.innerHTML = key;

    var childrenUl = createTreeDom(obj[key]);
    if (childrenUl) li.appendChild(childrenUl);

    ul.appendChild(li);
  }

  return ul;
}

这是沙盒的链接,它的完整代码为:http://jsbin.com/zonoxereqa/1/edit

我如何很好地理解这些功能:

function isObjectEmpty(obj) {
  for (var key in obj) {
    return false;
  }
  return true;
}

function createTree(container, obj) {
  container.appendChild( createTreeDom(obj) );
}

只有createTreeDom(obj)递归函数我不太了解她的工作,请帮我解释一下她的工作。

我仍然不明白为变量childrenUl分配了什么?为什么它总是在调试器中未定义?

1 个答案:

答案 0 :(得分:2)

它使用嵌套对象创建嵌套列表。在一个级别嵌套中,它创建一个单级简单ul li, li ...列表。但是如果某些值是非空对象,就像这样

var arg = { "one":{}, "two":{}, "three":{"subone":{}, "subtwo":{}}, "four":{}};

然后将子对象作为递归

中的子列表附加
var childrenUl = createTreeDom(obj[key]);
if (childrenUl) li.appendChild(childrenUl);

如果该值不是空对象,则不会创建子列表,因为第一个命令存在停止条件:

if (isObjectEmpty(obj)) return;

上面的数组一步一步:对于第一个项目,该函数创建ul元素并添加likey="one"obj[key]={}:< / p>

<ul>
  <li>one</li>
</ul>

但尚未完成,现在称为递归:createTreeDom({})。由于isObjectEmpty({})(显然)返回true,递归结束并且childrenUl未定义。因此,没有内容添加到li并且循环跳转到第二个节点,这也只是一个简单的字符串文字,因此它添加了另一个li节点:

<ul>
  <li>one</li>
  <li>two</li>
</ul>

现在重点:第三个论点。在执行递归之前,它看起来像这样:

<ul>
  <li>one</li>
  <li>two</li>
  <li>three</li>
</ul>

但是第三个成员的值不是空对象,所以命令

if (childrenUl) li.appendChild(childrenUl);

创建一个ul节点,如上所述逐步填充其内容,将其添加到li元素:

<ul>
  <li>one</li>
  <li>two</li>
  <li>three
    <ul>
      <li>subone</li>
      <li>subtwo</li>
    </ul>
  </li>
</ul>

如果某些嵌套项包含另一个非空对象,则它将作为子子列表附加到某个子列表li,依此类推。

读取等效内容可能会更好:

function createTreeDom(obj) {
  var ul = document.createElement('ul');

  for (var key in obj) {
    var li = document.createElement('li');
    li.innerHTML = key;

    if (!isObjectEmpty(obj[key])) {
      var childrenUl = createTreeDom(obj[key]);
      li.appendChild(childrenUl);
    }

    ul.appendChild(li);
  }

  return ul;
}