【问题标题】:How can I replace one class with another on all elements, using just the DOM?如何仅使用 DOM 在所有元素上用另一个类替换一个类?
【发布时间】:2025-12-23 04:45:11
【问题描述】:

我只想将一个类名更改为另一个类名。

我试过了

document.getElementsByClassName("current").setAttribute("class", "none");

但它不起作用。我是 javascript 新手。

【问题讨论】:

标签: javascript dom


【解决方案1】:

说明

document.getElementsByClassName 返回一个HTMLCollection,而不仅仅是一个元素数组。这意味着该集合是实时的,因此在这种特定情况下,它保留了将 始终 保存 所有 类为“current”的元素的要求。

巧合的是,您正在删除集合所依赖的 class,因此更新了集合。如果您在循环中设置value 属性(例如),那将完全不同——集合不会受到影响,因为class“当前”没有被删除。如果您添加一个类,例如el.className += " none";,情况也会完全不同,但事实并非如此。

来自 MDN 文档的精彩描述:

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

方法 1

克服所有这些混乱的简单方法是向后循环。

var els = document.getElementsByClassName('current'),
    i = els.length;

while (i--) {
    els[i].className = 'none';
}

演示: http://jsfiddle.net/fAJgT/

(演示中的代码有一个setTimeout,只是为了让你先看到原来的边框颜色,然后在1.5秒后看到它的变化)

这是有效的,因为它修改了集合中的最后一个项目 - 当它被修改(并自动删除)时,移动到它之前的项目。所以它不会遭受自动删除的任何后果。

另一种设置,做同样的事情,是:

for (i = els.length; i >= 0; i--) {

方法2

另一个答案让我意识到你可以不断地对找到的第一个项目进行操作。当您删除特定类时,该元素将从集合中删除,因此您可以保证第一项始终是集合中的新项目。因此,检查length 属性应该是一个安全的检查条件。这是一个例子:

var els = document.getElementsByClassName('current');
while (els.length) {
    els[0].className = 'none';
}

演示: http://jsfiddle.net/EJLXe/

这基本上是说“当集合中还有项目时,修改第一个(修改后将被删除)”。不过,我真的不建议您使用该方法,因为它仅特别是因为您最终会修改集合才有效。如果您没有删除特定类,或者使用普通数组或非实时集合(没有spliceing),这将无限循环。

方法 3

另一个选择是将slice(浅拷贝)集合到一个数组中并正常循环。但我看不出有任何理由/改进这样做。无论如何,这是一个示例:

var els = document.getElementsByClassName('current'),
    sliced = Array.prototype.slice.call(els), i;

for (i = 0; i < sliced.length; i++) {
    sliced[i].className = 'none';
}

演示: http://jsfiddle.net/LHe95/2/

方法 4

最后,你可以使用document.querySelector - 它返回一个非实时NodeList(因此你可以像正常一样循环),甚至有更好的支持浏览器比document.getElementsByClassName 不。这是一个例子:

var els = document.querySelectorAll('.current'),
    i;

for (i = 0; i < els.length; i++) {
    els[i].className = 'none';
}

演示: http://jsfiddle.net/xq8Xr/


参考资料:

【讨论】:

  • @plalx 我实际上并没有反对你的投票 - 但我也没有反对
  • 我仍然看不到反向迭代的目的。
  • +1,这是一个有效的点,否则只会改变每隔一个元素!
  • 呃,从来没有意识到这一点。 +1
  • 我想我们中的大多数人从来没有考虑过这个问题,因为我们只是这样做$('.current').addClass('someClass');
【解决方案2】:

document.getElementsByClassName("current") 返回 HTMLCollection,而不是 HTMLElement。您可以像访问数组一样访问列表中的元素。

以下将更改HTMLCollection中第一个元素的类。

document.getElementsByClassName("current")[0].setAttribute("class", "none");

但是,您不必使用setAttribute 方法,您只需设置元素的className 属性即可。

 element.className = 'none';

请注意HTMLCollection 是活动的,这意味着一旦元素不再具有current 类名,该元素将从数组中删除,以避免任何问题,您可以对其进行迭代使用以下方法:

var list = document.getElementsByClassName("current");

while (list.length) {
    list[0].className = 'none';
}

【讨论】:

  • 新循环的另一个选项是 while (list.length) { list[0].className = 'none'; }
  • 如果每次迭代都选择相同的元素,迭代的意义何在?
  • @adeneo 迭代只是确保它迭代正确的次数。如果您总是修改集合中的第一项,则该项将始终从其中删除。
  • @Ian - 啊哈,我明白了。你会在 SO 上看到最奇怪的东西!
最近更新 更多