【问题标题】:Array.from() not converting nodeList into an arrayArray.from() 未将 nodeList 转换为数组
【发布时间】:2021-05-02 08:18:45
【问题描述】:

我使用 createElement() 创建了一个列表元素的 nodeList。然后我使用 Array.from() 将有问题的 nodeList 转换为我可以迭代的数组。我想根据索引的值应用不同的宽度。如果索引是 300px 的偶数宽度,则为 500px 的宽度。但是,控制台返回“Cannot read property 'style' of undefined at bottleOnTheWall”。

我还使用 [...] 将我的 nodeList 转换为数组,但也没有成功。我的猜测是,它首先不是 nodeList,这意味着它不能转换为数组。至少不使用这两种方法中的任何一种。

我想知道是否有人可以指出我出错的地方并修复我的代码。我一直在尝试这样做,这对健康有益。

const bottles = document.getElementById("bottles");
count = 99;
var myArray = [];
var j = 0;

function bottlesOnTheWall() {
  while (count > 0) {
    if(count > 2) {
      myArray.push(`${count} bottles of beer on the wall, ${count} bottles of beers. Take one down and pass it around, ${count - 1} bottles of beer on the wall`)
    } else if (count === 2) {
      myArray.push(`${count} bottles of beer on the wall, ${count} bottles of beers. Take one down and pass it around, ${count - 1}bottle of beer on the wall`)
    } else if (count === 1) {
      myArray.push(`${count} bottle of beer on the wall, ${count} bottles of beers. No more bottle of beer on the wall`)
    } else {
      myArray.push(`No more bottles of beer on the wall. No more bottles of beer.  Go to the shop and buy some ${count} more.`)
    }
    count--
  }
  while (j < myArray.length) {
    var liElement = document.createElement("li");
    var text = document.createTextNode(myArray[j]);
    liElement.appendChild(text);
    bottles.appendChild(liElement);
    var bottlesArray = Array.from(bottles);
    if(j % 2) {
      bottlesArray[j].style.width = "300px";
    } else {
      bottlesArray[j].style.width = "500px";
    }
    j++;
  }
}
bottlesOnTheWall();
#bottles {
  line-height: 2;
  letter-spacing: 3px;
}

/* ul {
  list-style-image: url('beer.png');
} */

body {
  background: #FFF8DC;
}

li {
  max-width: 500px;
  margin: auto;
  margin-bottom: 10px;
}

ul li {
  background: #FFEBCD;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>bottles on the wall</title>
    <link rel="stylesheet" href="index.css">
  </head>
  <body>
    <ul id="bottles" ></ul>
    <script src="index.js" type="text/javascript"></script>

  </body>
</html>

【问题讨论】:

  • const bottles = document.getElementById("bottles"); 返回一个节点,而不是节点列表。 Array.from(bottles) 因此尝试将节点转换为数组。
  • 另外,我不太确定为什么要转换为数组 bottlesArray[j].style.width = "some width"; 意味着您要转换为数组只是为了从中获取最后一个索引 j。如果您想要最后一个附加元素,它可能只是 liElement.style.width = "some width";
  • 还有一个问题,为什么要先创建一个数组,然后再迭代呢?

标签: javascript html arrays nodelist


【解决方案1】:

Array.from 需要一个带有已实现Symbol.iterator 的变量。单个元素没有它,而是元素列表,这里不给出。

那么你还有一些问题:

  • 全局变量,但仅在单个函数中使用。只需移动函数内的所有变量即可。

  • count取一个参数。

  • 进行一个循环而不首先将所有文本收集到一个数组中,然后再次迭代以创建元素。唯一的目的是使用层模型将数据集合与表示层分开。

  • 最后把conditional (ternary) operator ?: 换成width

function bottlesOnTheWall(count) {
    const bottles = document.getElementById("bottles");
    
    while (count > 0) {
        let text;

        if (count > 2) text = `${count} bottles of beer on the wall, ${count} bottles of beers. Take one down and pass it around, ${count - 1} bottles of beer on the wall`;
        else if (count === 2) text = `${count} bottles of beer on the wall, ${count} bottles of beers. Take one down and pass it around, ${count - 1} bottle of beer on the wall`;
        else if (count === 1) text = `${count} bottle of beer on the wall, ${count} bottles of beers. No more bottle of beer on the wall`;
        else text = `No more bottles of beer on the wall. No more bottles of beer.  Go to the shop and buy some ${count} more.`;

        count--;

        const liElement = document.createElement("li");
        liElement.appendChild(document.createTextNode(text));
        bottles.appendChild(liElement);
        liElement.style.width = count % 2
            ? "300px"
            : "500px";
    }
}

bottlesOnTheWall(99);
#bottles { line-height: 2; letter-spacing: 3px; }
body { background: #FFF8DC; }
li { max-width: 500px; margin: auto; margin-bottom: 10px; }
ul li { background: #FFEBCD; }
&lt;ul id="bottles"&gt;&lt;/ul&gt;

【讨论】:

    【解决方案2】:

    您可以进一步推动 DRY 原则,并通过这样做来缩短脚本。 &lt;li&gt;s 的交替宽度可以通过使用简单的 CSS 选择器来强制执行:li:nth-child(even) { max-width:300px }

    函数bob(n) 生成一个指定啤酒瓶数的字符串,并在bottlesOnTheWall() 函数中定义。然后它可以在任何地方使用,并提供一个带有任意数量n 的正确变形字符串。

    function bottlesOnTheWall(count) {
      let n=count;
      const LIs=[],
            bob=n=>(n>1?n:(n==0?'no more':1))+' bottle'+(n==1?'':'s')+' of beer';       
      do {
        LIs.push('<li>'+bob(n)[0].toUpperCase()+bob(n).substring(1)+' on the wall, '
        +bob(n)+'. '
        +(n?`Take one down and pass it around, ${bob(n-1)} on the wall`
           :`No more bottles of beer.  Go to the shop and buy some ${count} more.`)
        +'</li>'
        );
      } while(n--)
      document.getElementById("bottles").innerHTML=LIs.join('\n')    
    }
    
    bottlesOnTheWall(9);
    #bottles { line-height: 2; letter-spacing: 3px; }
    body { background: #FFF8DC; }
    li { max-width:500px; margin: auto; margin-bottom: 10px; }
    li:nth-child(even) { max-width:300px }
    ul li { background: #FFEBCD; }
    &lt;ul id="bottles"&gt;&lt;/ul&gt;

    【讨论】:

      猜你喜欢
      • 2014-09-12
      • 2014-03-14
      • 2016-08-27
      • 2018-09-21
      • 1970-01-01
      • 2011-11-19
      • 2021-01-14
      • 2012-05-05
      • 2021-02-06
      相关资源
      最近更新 更多