Как исправить рекурсивную функцию, когда последние возвращают все остальные результаты в JavaScript? - PullRequest
0 голосов
/ 14 сентября 2018

Я пытаюсь написать функцию, которая рекурсивно добавляет детей в DOM на основе объекта JSON.

Проблема, с которой я сталкиваюсь, заключается в том, что последний 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 голосов
/ 14 сентября 2018

В вашем коде есть несколько недостатков:

  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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...