如何从纯 JavaScript 中的元素中删除类?

IT技术 javascript getelementsbyclassname
2021-02-06 09:48:19

我想知道如何选择类名为“widget”和“hover”的所有元素,然后从这些元素中删除类“hover”。

我有以下 JavaScript 代码,用于选择具有“widget”和“hover”类的所有元素:

var elements = document.getElementsByClassName('widget hover');
console.log(elements);

这似乎有效并输出如下内容(没有错误):

[div#.widget... 

问题是,如果我尝试删除“悬停”类,则会出现错误:

var elements = document.getElementsByClassName('widget hover');
console.log(elements);
elements.classList.remove("hover");

这输出:

[item: function]
length: 0
Uncaught TypeError: Cannot call method 'remove' of undefined 

谁能告诉我我做错了什么?


请注意,我在 jQuery 中使用了它:

$('.widget.hover').removeClass('hover');

...但我正在寻找纯 JavaScript 的解决方案。

6个回答
var elems = document.querySelectorAll(".widget.hover");

[].forEach.call(elems, function(el) {
    el.classList.remove("hover");
});

您可以修补.classList到 IE9。否则,您将需要修改.className.

var elems = document.querySelectorAll(".widget.hover");

[].forEach.call(elems, function(el) {
    el.className = el.className.replace(/\bhover\b/, "");
});

.forEach()还需要IE8的补丁,但是这是很常见的反正。

因为你是第一个回答的,所以我给你。
2021-03-30 09:48:19
@Andrew:.className.replace()如果类可能包含字母数字字符以外的字符,则应该更复杂一些。例如,如果一个类可以是hover-me,则该hover部分可能会被正则表达式匹配。不确定您需要多广泛的解决方案。
2021-04-08 09:48:19
@Andrew:我不是第一个,但另一个答案确实需要修正。
2021-04-13 09:48:19

查找元素:

var elements = document.getElementsByClassName('widget hover');

由于elements是一个live数组并反映了所有 dom 更改,因此您可以hover使用简单的 while 循环删除所有类:

while(elements.length > 0){
    elements[0].classList.remove('hover');
}

现在是 2021 年...保持简单,只需使用 es6

时代变了,现在最干净、最易读的方法是:

Array.from(document.querySelectorAll('.widget.hover')).forEach((el) => el.classList.remove('hover'));

如果您不能支持箭头函数,那么只需将其转换为:

Array.from(document.querySelectorAll('.widget.hover')).forEach(function(el) { 
    el.classList.remove('hover');
});

此外,如果您需要支持非常旧的浏览器,然后用polyfilforEachArray.from与您的生活。

querySelectorAll这样做不是更现代的方式吗?
2021-03-16 09:48:19
@Qasim 我应该强调我的重点不是你如何获得元素,而是你如何使用Array.from删除它们forEach
2021-03-21 09:48:19
你可以乘坐 Array.from: (document.querySelectorAll("div")).forEach((el) => el.classList.remove("selected"));
2021-03-21 09:48:19
我试过没有“Array.from”,它似乎也有效,请告诉我使用“Array.from”是否有任何特殊目的。
2021-04-09 09:48:19
@Danie - 这仍然有效,两者之间的区别在于一个引用 aNodeList[]Array.from引用 an Array[]有关更多信息请参阅此文章
2021-04-13 09:48:19

Elements 是一个 DOM 对象数组。你应该做这样的事情:

for (var i = 0; i < elements.length; i++) {
   elements[i].classList.remove('hover');
}

枚举元素集合并为集合内的每个元素调用该remove方法

@MattBaker 你的版本有效,但不是因为它是递归版本,它只有效是因为 getElementsByClassName 返回“live”数组,所以当你从 0-up 删除类时,它们从“live”数组中消失。当您隐藏第 0 个项目时,第 1 个项目移动到第 0 个位置,但您从第 1 个项目继续循环,从而使第 0 个项目与类保持一致。从头开始解决了这个问题。
2021-03-15 09:48:19
这完美地工作。我没有意识到元素将是一个数组,所以这是非常有意义的。有没有更快的东西不必重新遍历整个数组?
2021-03-17 09:48:19
我相信没有比这更快的了。JQuery 可能应该做类似的事情。但是不要担心速度,您必须拥有数千(如果不是数百万)个元素才能看到性能问题
2021-03-19 09:48:19
需要考虑的一件事是,在问题中,.getElementsByClassName被用来获取元素。因为您要删除用于获取的类之一,该元素将从elements列表中删除,这意味着该列表将被重新索引,并且您最终会跳过某些元素。反向迭代更安全。
2021-03-23 09:48:19
根据@饼干怪兽的角度来看,这里的递归版本:for (var i = elements.length-1; i > -1; i--) {}
2021-04-14 09:48:19

对于 ES6,这可以通过一个 liners以多种方式完成,您可以在其中使用扩展运算符创建元素数组...,并使用map运算符删除类

querySelectorAll

[...document.querySelectorAll('.widget')].map(x => x.classList.remove('hover'));

getElementsByClassName

[...document.getElementsByClassName('widget')].map(x => x.classList.remove('hover'));

对于querySelectorAll,请注意使用.widget代替widget扩展运算符的替代方法是使用Array.from如下:

Array.from(document.querySelectorAll('.widget')).map(x => x.classList.remove('hover'));