【问题标题】:JavaScript: How to create unordered list from array?JavaScript:如何从数组创建无序列表?
【发布时间】:2017-05-12 04:37:57
【问题描述】:

我有以下数组,我想从中创建一个无序列表,但是我无法以正确的格式生成无序列表。我搜索了类似的问题,但现有的解决方案都不适用于我的问题。

var myArray = ['Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'], 'Value 2', 'Value 3', 'Value 4', 'Value 5', 'Value 6'];

这是我的 JavaScript 代码:

function arrToUl(arr) {
  var div = document.getElementById('myList');
  var ul = document.createElement('ul');

  for (var i = 0; i < arr.length; i++) {

    if (arr[i] instanceof Array) {
      var list = arrToUl(arr[i]);
    } else {
      var li = document.createElement('li');
      li.appendChild(document.createTextNode(arr[i]));
      console.log(ul.appendChild(li));
    }
    div.appendChild(ul);
  }
}

arrToUl(myArray);

以上代码产生以下结果:

<ul>
<li>Value 1</li>
<li>Inner Value 1</li>
<li>Inner Value 2</li>
<li>Inner Value 3</li>
<li>Inner Value 4</li>
<li>Value 2</li>
<li>Value 3</li>
<li>Value 4</li >
<li>Value 5</li >
<li>Value 6</li>

但结果应该如下所示:

<ul>
<li>Value 1
    <ul>
        <li>Inner Value 1</li>
        <li>Inner Value 2</li>
        <li>Inner Value 3</li>
        <li>Inner Value 4</li>
    </ul>
</li>
<li>Value 2</li>
<li>Value 3</li>
<li>Value 4</li>
<li>Value 5</li>
<li>Value 6</li>

感谢您的帮助。

【问题讨论】:

  • 问:如果myArray = ['Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'], 应该是什么结果? ['内值 5'、'内值 6'、'内值 7'、'内值 8']、'值 2'、'值 3'、'值 4'、'值 5'、'值 6' ] ?
  • 使用instanceof检测Array不可靠,请改用Array.isArray

标签: javascript html arrays for-loop


【解决方案1】:

您已将所有 &lt;ul&gt; 元素附加到 myList &lt;div&gt;。为了改变这一点,我在arrToUl(root, arr) 函数中添加了一个新参数。

新的参数root决定了创建的&lt;ul&gt;应该被追加到谁,所以如果函数遇到子数组,它使用之前的列表项作为创建子列表的根.

var myArray = ['Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'], 'Value 2', 'Value 3', 'Value 4', 'Value 5', 'Value 6'];

function arrToUl(root, arr) {
  var ul = document.createElement('ul');
  var li;
  
  root.appendChild(ul); // append the created ul to the root

  arr.forEach(function(item) {
    if (Array.isArray(item)) { // if it's an array
      arrToUl(li, item); // call arrToUl with the li as the root
      return;
    }
    
    li = document.createElement('li'); // create a new list item
    li.appendChild(document.createTextNode(item)); // append the text to the li
    ul.appendChild(li); // append the list item to the ul
  });
}

var div = document.getElementById('myList');

arrToUl(div, myArray);
&lt;div id="myList"&gt;&lt;/div&gt;

【讨论】:

  • append 仅...?
  • 错误:“message”:“对象不支持属性或方法'append'”,
  • 是像ParentNode.append这样的jQuery,看来是缺乏支持。谢谢:)
【解决方案2】:

您的函数称为arrToUl,因此它应该这样做:将数组转换为ul

一旦你有了ul,你就可以将它插入到任何你想要的地方,但是把它放在函数之外。

然后一切都变得清晰了。

function arrToUl(arr) {
  var ul = document.createElement('ul'), li;
  for (var i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      li.appendChild(arrToUl(arr[i]));
    } else {
      li = document.createElement('li');
      li.appendChild(document.createTextNode(arr[i]));
      ul.appendChild(li);
    }
  }
  return ul;
}
var myArray = ['Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'], 'Value 2', 'Value 3', 'Value 4', 'Value 5', 'Value 6'];
document.body.appendChild(arrToUl(myArray));

【讨论】:

    【解决方案3】:

    你的递归方法没有说明它应该在哪里附加新的孩子。也许您应该在每次获得数组实例时给最后一个元素一个唯一的 id。然后你可以用你的函数参数给这个 id。

    GUID Generator 是制作唯一 id 的好方法。

    【讨论】:

    • 这不是答案,应该是评论。
    【解决方案4】:

    我会提出一个基于递归的解决方案,在我看来它更清晰且不易出错。它产生的结果略有不同,因为它将每个数组元素映射到同一级别的节点,我认为这应该是从数组创建 ul 的输出。

    var myArray = [
      'Value 1',
      ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'],
      'Value 2',
      'Value 3',
      'Value 4',
      'Value 5',
      'Value 6'
    ];
    
    function appendItems(arr, el) {
      if(!arr.length) return el;
      else {
          var head = arr.shift();
          var child = transform(head);
          var li = document.createElement('li');
          li.appendChild(child);
          el.appendChild(li);
          return appendItems(arr, el);
      }
    }
    
    function transform(item) {
      if(Array.isArray(item)) {
        var ul = document.createElement('ul');
        return appendItems(item, ul);
      } else {
        return document.createTextNode(item);
      }
    }
    
    var ul = transform(myArray);
    

    如果您希望获得您提到的输出,最好更改输入格式以匹配每个节点的一次迭代。 例如:

    var arr = [
      {label: 'value1', subitems: ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4']}
    ];
    

    【讨论】:

      【解决方案5】:

      您可以保存最后一个 li 并使用带有目标 DOM 元素的扩展函数附加到它。

      function iter(target) {
          var ul = document.createElement('ul'),
              li;
      
          target.appendChild(ul);
          return function (a) {
              if (Array.isArray(a)) {
                  if (!li) {
                      li = document.createElement('li');
                      ul.appendChild(li);
                  }
                  a.forEach(iter(li));
                  return;
              }
              li = document.createElement('li');
              li.appendChild(document.createTextNode(a));
              ul.appendChild(li);
          };
      }
      
      var myArray = ['Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'], 'Value 2', 'Value 3', 'Value 4', 'Value 5', 'Value 6'];
      
      myArray.forEach(iter(document.getElementById('myList')));
      &lt;div id="myList"&gt;&lt;/div&gt;

      【讨论】:

      • 感谢所有帮助。所有解决方案对我来说都很好。
      • @OriDrori,现在它会检查是否存在。
      【解决方案6】:

      使用 vanilla JS(使用 ES6 语法):

      const myArray = [
        "Value 1",
        ["Inner value 1", "Inner value 2", "Inner value 3", "Inner value 4"],
        "Value 2",
        "Value 3",
        "Value 4",
        "Value 5",
        "Value 6",
      ];
      
      const arrayToUL = (arr) => {
        const ul = document.createElement("ul");
        ul.append(
          ...arr.map((value) => {
            if (Array.isArray(value)) return arrayToUL(value);
            const li = document.createElement("li");
            li.textContent = value;
            return li;
          })
        );
        return ul;
      };
      
      document.body.appendChild(arrayToUL(myArray));

      在 ReactJS 中(将数组作为其子元素):

      const List = ({ children }) => (
        <ul>
          {children.map((val) =>
            Array.isArray(val) ? List({ children: val }) : <li>{val}</li>
          )}
        </ul>
      );
      
      const myArray = [
        "Value 1",
        ["Inner value 1", "Inner value 2", "Inner value 3", "Inner value 4"],
        "Value 2",
        "Value 3",
        "Value 4",
        "Value 5",
        "Value 6",
      ];
      
      const App = () => <List>{myArray}</List>;
      
      ReactDOM.render(<App />, document.getElementById("root"));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
      <div id="root"></div>

      【讨论】:

        猜你喜欢
        • 2022-06-15
        • 2013-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-06
        • 1970-01-01
        • 1970-01-01
        • 2013-11-06
        相关资源
        最近更新 更多