JavaScript:如何从数组创建无序列表?

时间:2016-12-27 22:13:59

标签: javascript html arrays for-loop

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

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>

感谢您的帮助。

6 个答案:

答案 0 :(得分:5)

您已将所有CSS元素附加到myList <ul>。为了改变这种情况,我在<div>函数中添加了一个新参数。

新参数arrToUl(root, arr)确定应该追加创建的root的人,因此如果函数遇到子数组,它会使用前一个列表项作为创建子列表。

&#13;
&#13;
<ul>
&#13;
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);
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您的函数名为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));

答案 2 :(得分:0)

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

&#13;
&#13;
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')));
&#13;
<div id="myList"></div>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

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

GUID Generator是制作唯一身份证的好方法。

答案 4 :(得分:0)

我建议基于递归的解决方案,在我看来更清晰,更不容易出错。它产生一个稍微不同的结果,因为它将每个数组元素映射到同一级别的节点,我认为这应该是从数组创建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 :(得分:0)

使用 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>