className 只更改每隔一个类

IT技术 javascript html css
2021-02-21 13:52:44

我正在使用 JavaScript 执行一个小文本,但getElementsByClassName()得到了一些不需要的结果。我希望脚本将每个 CSS 类更改为一个新类。问题是每个其他class都只是在改变......

我想使用纯 js 如何解决这个问题,因为它是出于实践目的。

想到的第一件事是空格,尽管在删除时这没有任何区别。

谁能指出我们做错了什么?

<html>
    <head>
       <link rel="stylesheet" type="text/css" href="default.css">
    </head>
    <body>
        <div class="block-default">BLOCK1</div>
        <div class="block-default">BLOCK2</div>
        <div class="block-default">BLOCK3</div>
        <div class="block-default">BLOCK4</div>
        <div class="block-default">BLOCK5</div>
        <div class="block-default">BLOCK6</div>
        <div class="block-default">BLOCK7</div>
        <div class="block-default">BLOCK8</div>
        <script>

    var blockSet = document.getElementsByClassName("block-default");
    var blockSetLength = blockSet.length;

    blockSet[0].className = "block-selected";
    blockSet[1].className = "block-selected";
    blockSet[2].className = "block-selected";
    blockSet[3].className = "block-selected";
    blockSet[4].className = "block-selected";
    blockSet[5].className = "block-selected";
    blockSet[6].className = "block-selected";
    blockSet[7].className = "block-selected";   

        </script>
    </body>
</html>

CSS类:

.block-default {
    width: 100px;
    height:50px;
    background-color: green;
    border: 1px solid red;
    padding:10px;
}

.block-selected {
    width: 100px;
    height:50px;
    background-color: blue;
    border: 1px solid white;
    padding:10px;
 }
6个回答

因为你改变.className了的blockSet这是一个HTMLCollectionblock-default当元素发生某些更新时,具有相同类 ( )元素的集合将发生变化。

换句话说,当您更改.className元素的 时,集合将排除该元素。这意味着规模HTMLCollection减少如果具有该类的元素已添加到 DOM,大小也会增加

要解决这个问题,您始终可以只更改第一个元素.className

for(var i = 0; i<blockSetLength; i++)
{
    blockSet[0].className = "block-selected";
}

注意:除了逐个元素更改类元素,您可以使用for和 更改遍历元素.className

如果您在 DOM(不是集合)中添加新项目,则大小将增加,如下例所示。

非常有用的解释!
2021-04-23 13:52:44

您可以使用不是使用getElementsByClassName()
它返回一个将随着s 更改而更改实时 HTMLCollection它返回一个不会更改非实时NodeListclassName
querySelectorAll()

querySelectorAll()getElementsByClassName()(IE8+ 与 IE9+)有更好的 IE 支持
它也更加灵活,因为它支持 CSS 选择器(IE8+ 的 CSS2 和 IE9+ 的 CSS3)。

然而,querySelectorAll()getElementsByClassName()
如果您正在处理数以千计的 DOM 元素,请记住这一点。

片段

这可能是最安全的方法。所有其他解决方案都建议在实时集合中设置第一个项目,这在非常特定的情况下仍然存在问题。
2021-05-10 13:52:44
如果您querySelectorAll出于任何原因不想使用,或者只是想要一个替代解决方案,您可以使用Array.from(liveNodeList)[].slice.call(liveNodeList)将 转换liveNodeList为静态可变数组。
2021-05-20 13:52:44

通过为.className分配一个值,您可以覆盖该元素上的每个类。您可能想要查看的是.classList属性。

删除一个类:

blockSet[0].classList.remove('block-default');

添加新类:

blockSet[0].classList.add('block-selected');

一个很好的起点,当你尝试做一些事情时,jQuery 通常为你做的,是http://youmightnotneedjquery.com/

获得 +1,因为您提出了一些实际合理的建议:Element.classList
2021-05-09 13:52:44

你已经有了一些很好的解决方案。

我认为最好的是里克希区柯克的那一部。

但是我经常使用的一个解决方案是在做这样的事情时安全起见,是将集合向后移动

var nmax = blockSet.length - 1;
for (var n=nmax; n>=0; n--) {
    blockSet[n].className = 'block-selected';
}

这将您与集合中的更改隔离开来

这是最好的解决方案;关键是与getElementsByClassName一起工作是与将立即更新的实时数据结构进行交互……向后循环不会影响您的索引。
2021-05-10 13:52:44

document.getElementsByClassName 返回一个HTMLCollection对象,它是实时的

HTML DOM 中的 HTMLCollection 是活动的;当基础文档更改时,它会自动更新。

所以当你打电话

blockSet[0].className = "block-selected";

您更改了基础文档并且该项目不再在集合中(blockSet[0] 现在是您原始选择中的第二个项目)。

用于var blockSet = Array.slice.call (document.getElementsByClassName("block-default"));将 HTML 集合转换为常规数组。
2021-04-24 13:52:44
确切地。值得一提的是,jQuery 使用的是数组,而不是 HTMLCollection 调用时$(".block-default"),因此您无法使用该库实现此行为。
2021-05-11 13:52:44