JavaScript的classList.remove不能正常工作

10

看看这个 JSFiddle:JSFiddle

HTML:

<table class="myTable">
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class=" someStyle">1</span>/<span class="otherStyle">15</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class=" someStyle">2</span>/<span class="otherStyle">16</span>
    </td>
  </tr>
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class="">3</span>/<span class="">17</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class="otherStyle">4</span>/<span class=" someStyle">18</span>
    </td>
  </tr>
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class="otherStyle">5</span>/<span class=" someStyle">19</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class="">6</span>/<span class="">20</span>
    </td>
  </tr>
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class="">7</span>/<span class="">21</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class=" someStyle">8</span>/<span class="otherStyle">22</span>
    </td>
  </tr>
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class="">9</span>/<span class="">23</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class="otherStyle">10</span>/<span class=" someStyle">24</span>
    </td>
  </tr>
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class="otherStyle">11</span>/<span class=" someStyle">25</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class="otherStyle">12</span>/<span class=" someStyle">26</span>
    </td>
  </tr>
  <tr>
    <th>Some text</th>
    <td class="align">
      <span class=" someStyle">13</span>/<span class="otherStyle">27</span>
    </td>
    <th>Some text</th>
    <td class="align">
      <span class=" someStyle">14</span>/<span class="otherStyle">28</span>
    </td>
  </tr>
</table>

JavaScript:

var myTbl = document.getElementsByClassName("myTable")[0];

var tSomeStyleClasses = myTbl.getElementsByClassName("someStyle");
console.log(tSomeStyleClasses);
for (i=0;i<tSomeStyleClasses.length;i++) {
    console.log(tSomeStyleClasses[i].classList);
    //tSomeStyleClasses[i].classList.remove("someStyle");
}

var tOtherStyleClasses = myTbl.getElementsByClassName("otherStyle");
console.log(tOtherStyleClasses);
for (i=0;i<tOtherStyleClasses.length;i++) {
    console.log(tOtherStyleClasses[i].classList);
    //tOtherStyleClasses[i].classList.remove("otherStyle");
}

然后检查控制台日志。每个,someStyle和otherStyle都有10个条目。现在取消注释//tSomeStyleClasses[i].classList.remove("someStyle");//tOtherStyleClasses[i].classList.remove("otherStyle"); 然后运行fiddle。再次检查控制台日志。应该删除2 x 10的样式,但实际上只删除了5个样式。

4个回答

21

.getElementsByClassName() 返回的值是一个实时的 NodeList。这意味着当你更改列表中的元素时,列表本身会自动更新。因此,当你删除用于查找元素的类时,列表就会变短。因为你正在使用数字索引进行迭代,所以你最终会跳过一些元素。

处理这种情况的好方法是使用一个简单的while循环,并且只对列表中的第一个元素进行操作,直到列表为空:

var tSomeStyleClasses = myTbl.getElementsByClassName("someStyle");

while (tSomeStyleClasses.length) {
    tSomeStyleClasses[0].classList.remove("someStyle");
}

10
因为 getElementsByClassName 返回的是一个实时的匹配元素列表。当你从索引0的元素中移除类名时,该列表会立即更新以将该元素从列表中删除并将其他所有元素下移。由于你随后递增了i,因此现在位于索引0的元素不会被处理。
要么:
  1. 反向处理列表,或者

  2. 使用document.querySelectorAll(".someStyle"),它返回的是一个快照列表,而不是实时的列表


  1. 或者是 Pointy 建议的 while 循环。:-D
- T.J. Crowder
1
我一直想知道是哪位疯狂的天才首先提出了“live”节点列表的想法,因为这真的很不寻常。 - Pointy
哪一个更快?querySelectorAll、while循环还是带有递减索引的if循环? - Tomo
我选择了while循环,但我觉得还有更好的选择。我只是想知道哪个(假设)更正确或更快速。 - Tomo
@Tomo:没有一个是“更正确”的。就速度而言,你需要测试你的目标浏览器;我敢打赌它会有所不同。 - T.J. Crowder
显示剩余2条评论

0
我发现最简单且完美的方法是使用以下代码: -someElementToRemoveClassName-.classList.value = "" 这会清除整个 ClassName 列表并将其返回到原始状态,让你们重新添加过渡类,并像往常一样再次出现过渡效果。

欢迎来到 Stack Overflow _ 如果您在代码块中写入 classList.value = " "; 并删除不必要的图像链接,那么您的答案可能会更清晰。 - inputforcolor

0

对于那些更喜欢使用 for 循环而不是 while 循环,以及像 getElementsByTagName 这样的函数名而不是 querySelectorAll 的人,您也可以使用相同的函数并使用 Array.from 创建快照:

Array.from(getElementsByClassName("someStyle"))

或者展开语法:

[...getElementsByClassName("someStyle")]

然后,您可以使用您选择的for循环对其进行迭代(尽管请记住,只有其中一些与async/await良好地配合工作)。

注意:由于声望不足,我无法将此添加为评论,但这似乎可以成为T.J. Crowder答案的评论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接