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

问题描述 投票:1回答:1

我正在尝试编写一个函数,以递归方式将基于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我的函数的每一步,我可以看到我的函数如何正确地逐步通过子元素,问题是它不会按照它们应该去的方式追加它们。

javascript dom recursion
1个回答
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>
© www.soinside.com 2019 - 2024. All rights reserved.