HTML + Javascript:不能一次从两个元素中获取所有实例?

Posted

技术标签:

【中文标题】HTML + Javascript:不能一次从两个元素中获取所有实例?【英文标题】:HTML + Javascript: can't get all instances from two elements at once? 【发布时间】: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标签中?

【问题讨论】:

您应该检查浏览器控制台是否有错误。 【参考方案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。 Добро пожаловать! :)

以上是关于HTML + Javascript:不能一次从两个元素中获取所有实例?的主要内容,如果未能解决你的问题,请参考以下文章

一次从 OpenCV 中的两个摄像头捕获视频

一次从一个 TCP 套接字发送超过 32768 个字节到另一个

一次从多个分区中选择

ef core 如何一次从具有外键的不同表中获取数据? (数据库优先)

华为OD机试 - 找到它(JavaScript) | 机试题+算法思路+考点+代码解析 2023

求两个数组的交集