如何修复JavaScript中最后一次返回所有其他结果的递归函数?

时间:2018-09-13 23:23:43

标签: javascript dom recursion

我正在尝试编写一个函数,该函数基于JSON对象将子级追加到DOM。

我遇到的问题是递归中的最后一个return“覆盖”其他所有结果,但我不确定为什么。

这是我的代码:

var tags = [{
  tag: 'div',
  props: [{
    'class': 'meetup-container'
  }],
  children: [{
    tag: 'div',
    props: [{
      class: 'meetup',
      itemscope: '',
      itemtype: 'http://schema.org/Event'
    }],
    children: [{
      tag: 'p',
      props: [{
        itemprop: 'event'
      }]
    }],
  }]
}, {
  tag: 'a',
  props: [{
    href: '#'
  }]
}]

function buildDom(graph) {
  let element;

  graph.forEach((node) => {
    element = document.createElement(node.tag);

    if (node.props && node.props.constructor === Array) {
      node.props.forEach((prop) => {
        let propNames = Object.keys(prop);
        propNames.forEach((propName) => {
          return element.setAttribute(propName, prop[propName]);
        });
      });
    }

    if (node.children) {
      element.appendChild(buildDom(node.children));
      // return element.appendChild(buildDom(node.children));
    }
  });

  return element;
}

let elements = buildDom(tags);

基本上,我希望看到的输出是这样:

<div class="meetup-container">
  <div class="meetup">
      <p itemprop="event"></p>
  </div>
</div>

但是我看到的是这个

<p itemprop="event"></p> 

但是,如果我console.log函数的每一步,我都能看到我的函数如何正确地逐步遍历子元素,问题在于它没有按照应有的方式附加它们。

1 个答案:

答案 0 :(得分:4)

您的代码有一些缺陷:

  1. 如果数组graph中包含多个元素,则仅返回最后一个元素,而不返回预期的元素数组。要解决此问题,请使用map并返回结果数组。
  2. return中的forEach语句是没有用的。
  3. 函数buildDom应该返回元素数组,因为它需要一个对象数组(请参阅 1。),因此element.appendChild(buildDom(node.children));将不再起作用。使用forEach遍历该数组。

话虽这么说

function buildDom(graph) {
  return graph.map((node) => {
    let element = document.createElement(node.tag);

    if (node.props && Array.isArray(node.props)) {
      node.props.forEach((prop) => {
        let propNames = Object.keys(prop);
        propNames.forEach((propName) =>
          element.setAttribute(propName, prop[propName])
        );
      });
    }

    if (node.children) {
      buildDom(node.children).forEach(child => element.appendChild(child));
    }

    return element;
  });
}

示例:

function buildDom(graph) {
  return graph.map((node) => {
    let element = document.createElement(node.tag);

    if (node.props && Array.isArray(node.props)) {
      node.props.forEach((prop) => {
        let propNames = Object.keys(prop);
        propNames.forEach((propName) =>
          element.setAttribute(propName, prop[propName])
        );
      });
    }

    if (node.children) {
      buildDom(node.children).forEach(child => element.appendChild(child));
    }

    return element;
  });
}

let tags = [{"tag":"div","props":[{"class":"meetup-container"}],"children":[{"tag":"div","props":[{"class":"meetup","itemscope":"","itemtype":"http://schema.org/Event"}],"children":[{"tag":"p","props":[{"itemprop":"event"}]}]}]},{"tag":"a","props":[{"href":"#"}]}];

let result = document.getElementById("result"),
    elements = buildDom(tags);

elements.forEach(element => result.appendChild(element));
Result: (inspect element to see it)
<div id="result"></div>