【问题标题】:HTML + Javascript: can't get all instances from two elements at once?HTML + Javascript:不能一次从两个元素中获取所有实例?
【发布时间】:2021-11-19 03:47:45
【问题描述】:

我想为一组选择性元素的所有实例添加一个 CSS 样式类:例如,所有 p 元素以及所有 h4 元素。 p>

我定义了两个 JS 变量,它们获取上述标签的所有元素,并将它们插入到一个数组中,这样我就可以创建一个函数,理论上,应该将所选类应用于所选元素/标签的所有实例.

但是,当我运行代码时,该函数似乎只将类分配给数组的第一项。

<html>
  <head>
    <meta charset="utf-8">
    <title>JS Bin</title>
    <style>
      .italic { font-style: italic; }
    </style>
  </head>
    <body>
      <h4>Text goes in here</h4>
      <p>Text goes in here</p>

      <script>
        function styleTxt() {
          let h4Elems = document.getElementsByTagName("H4");
          let pElems = document.getElementsByTagName("P");
          const elemArray = [pElems, h4Elems];

          for (eachElem in elemArray) {
            let elemInsts = elemArray[eachElem];
            for (eachInst in elemInsts) {
              let givenInst = elemInsts[eachInst];
              givenInst.classList.add("italic");
            }
          }
        }
        styleTxt();
      </script>

    </body>
</html>

如果我颠倒数组中元素标签的顺序,则 h4 元素将获得 .italic 类,但 p元素不会。

也许不能两次使用“document”指令?是否有另一种方法可以将同一类自动添加到一组多个(但不是全部)html标签中?

【问题讨论】:

  • 您应该检查浏览器控制台是否有错误。

标签: javascript html css arrays dom


【解决方案1】:

您正在遍历 HTMLCollection 的每个属性,包括像 length 这样的属性,导致 givenInst 成为一个数字。由于它没有classList 属性,因此在undefined 上调用add 会产生错误并终止循环。

为了解决这个问题,你可以使用isNaN来检查属性是否为数字:

.italic {
  font-style: italics;
}
<html>

<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style>
    .italic {
      font-style: italic;
    }
  </style>
</head>

<body>
  <h4>Text goes in here</h4>
  <p>Text goes in here</p>

  <script>
    function styleTxt() {
      let h4Elems = document.getElementsByTagName("H4");
      let pElems = document.getElementsByTagName("P");
      const elemArray = [pElems, h4Elems];

      for (eachElem in elemArray) {
        let elemInsts = elemArray[eachElem];
        for (eachInst in elemInsts) {
          if (!isNaN(eachInst)) {
            let givenInst = elemInsts[eachInst];
            givenInst.classList.add("italic");
          }
        }
      }
    }
    styleTxt();
  </script>

</body>

</html>

但是,更好的方法是使用 for...of 循环:

.italic {
  font-style: italics;
}
<html>

<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style>
    .italic {
      font-style: italic;
    }
  </style>
</head>

<body>
  <h4>Text goes in here</h4>
  <p>Text goes in here</p>

  <script>
    function styleTxt() {
      let h4Elems = document.getElementsByTagName("H4");
      let pElems = document.getElementsByTagName("P");
      const elemArray = [pElems, h4Elems];

      for (eachElem of elemArray) {
        for (eachInst of eachElem) {
          eachInst.classList.add("italic");
        }
      }
    }
    styleTxt();
  </script>

</body>

</html>

【讨论】:

  • 您的第二个选择对我来说非常有效!我应该更多地了解 for...in 和 for...of 循环之间的区别;也许 for...of 循环是未来。
【解决方案2】:

试试这个

<html>

<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style>
    .italic {
      font-style: italic;
    }
  </style>
</head>

<body>
  <h4>Text goes in here</h4>
  <p>Text goes in here</p>

  <script>
    function styleTxt() {
      const h4Elems = Array.from(document.getElementsByTagName("H4"));
      const pElems = Array.from(document.getElementsByTagName("P"));
      const elemArray = [...pElems, ...h4Elems];

      elemArray.forEach(eachElem => {
        eachElem.classList.add("italic");
      })
    }

    styleTxt();
  </script>

</body>

</html>

【讨论】:

    【解决方案3】:

    使用Document.querySelectorAll() 获取这两种类型的元素。用NodeList.forEach() 迭代NodeList,并将类添加到每个元素。

    function styleTxt() {
      document.querySelectorAll('h4, p')
        .forEach(el => el.classList.add('italic'));
    }
    
    styleTxt();
    .italic {
      font-style: italic;
    }
    <h4>Text goes in here</h4>
    <p>Text goes in here</p>

    【讨论】:

      【解决方案4】:

      您可能更喜欢for...of 循环并使用spread operator。它将产生更好的代码输出:

      function styleTxt() {
          const h4Elems = document.getElementsByTagName("H4");
          const pElems = document.getElementsByTagName("P");
          const elemArray = [...pElems, ...h4Elems];
          for (const eachElem of elemArray) {
              eachElem.classList.add("italic");
          }
      }
      

      当然,您始终可以使用querySelectorAll 方法一次性选择两种类型的元素:

      const all = document.querySelectorAll("h4, p");
      
      // Using the for...of loop:
      for ( const el of all ){
        el.classList.add("italic");
      }
      
      // Using the `forEach` method:
      all.forEach( el => el.classList.add("italic") )
      

      【讨论】:

      • 感谢您的两种方法。我渴望成为一名 Web 开发人员,但我仍处于业余水平,因此还不熟悉 lambda 表达式。无论如何,我知道了 for...of 循环和扩展运算符,这些我都不知道。圣体圣事!
      • 在这种情况下,我会更好地重构我的代码以包含最佳实践:只要变量的值没有改变,就使用 const。 Добро пожаловать! :)
      猜你喜欢
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 2018-08-28
      • 2021-02-17
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多