从嵌套对象创建无序列表树-JavaScript

我有一个这样的嵌套对象:

const countries = {
  "Europe": {
    "France": {},
    "Spain": {}
  },
  "America": {
    "North": {
      "USA": {},
      "Canada": {}
    },
    "South": {
      "Brazil": {},
      "Argentina": {}
    }
  }
};

我想像这样从中创建一个无序列表:

<ul>
  <li>
    Europe:
    <ul>
      <li>France</li>
      <li>Spain</li>
    </ul>
  </li>
  <li>
    America:
    <ul>
      <li>
        North:
        <ul>
          <li>USA</li>
          <li>Canada</li>
        </ul>
      </li>
      <li>
        South:
        <ul>
          <li>Brazil</li>
          <li>Argentina</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

最后它不应该有任何空列表。

So far I tried this recursive approach, but it just returns a list with 2 items [object Object]:

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>data tree</title>
  </head>
  <body>
    <div id="container">

    </div>
    <script type="text/javascript">
      const countries = {
        "Europe": {
          "France": {},
          "Spain": {}
        },
        "America": {
          "North": {
            "USA": {},
            "Canada": {}
          },
          "South": {
            "Brazil": {},
            "Argentina": {}
          }
        }
      };

      //Getting the container were I want to put my list
      let container = document.getElementById('container');

      function createTree(container, data) {
        //Recursive function which will create as much lists as I need
        function rec(obj) {
          let list = document.createElement('ul');
          //Looping through the object properties
          for (let item in obj){
            //If the object property is object too
            //And it has its own properties
            //Then create a list ite for it 
            //And put a new list in it with the recursion
            if (Object.keys(obj[item]).length) {
              let listItem = document.createElement('li');
              listItem.textContent += obj[item];
              list.appendChild(listItem);
              rec(obj[item]);
            }
          }
          
          return list;
        }

        //In the end add the list to the container
        container.appendChild(rec(data));
      }

      createTree(container, countries);
    </script>
  </body>
</html>

如果可以用其他方法(例如循环或其他方法)来做到这一点,那也是可以接受的。

提前致谢。

评论
  • ’听天由命
    ’听天由命 回复

    You need to assign to the content of the created li on each iteration regardless - then check if the associated object has any keys, and if so, perform the recursive call:

    const countries = {
      "Europe": {
        "France": {},
        "Spain": {}
      },
      "America": {
        "North": {
          "USA": {},
          "Canada": {}
        },
        "South": {
          "Brazil": {},
          "Argentina": {}
        }
      }
    };
    
    function createTree(container, data) {
      const ul = container.appendChild(document.createElement('ul'));
      for (const [key, val] of Object.entries(data)) {
        const li = ul.appendChild(document.createElement('li'));
        li.textContent = key;
        if (Object.keys(val).length) {
          createTree(li, val);
        }
      }
    }
    
    createTree(document.getElementById('container'), countries);
    <div id="container">
    
    </div>