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

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

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

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

这似乎可以工作并输出类似的东西(没有错误) :

[div#.widget...

问题是,如果我试图删除类“ hover”,就会得到一个错误:

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 的解决方案。

160956 次浏览

Elements is an array of DOM objects. You should do something like this:

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

Enumerate the elements collection and for each element inside the collection call the remove method

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


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

You can patch .classList into IE9. Otherwise, you'll need to modify the .className.

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


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

The .forEach() also needs a patch for IE8, but that's pretty common anyway.

Find elements:

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

Since elements is a live array and reflects all dom changes you can remove all hover classes with a simple while loop:

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

This might help:

let allElements = Array.from(document.querySelectorAll('.widget.hover'));
for (let element of allElements) {
element.classList.remove('hover');
}

It's 2022... keep it simple and just use es6

Times have changed and now the cleanest and most readable way to do this is:

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

If you can't support arrow functions then just convert it like this:

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

Additionally if you need to support extremely old browsers then use a polyfil for the forEach and Array.from and move on with your life.

Given worked for me.

document.querySelectorAll(".widget.hover").forEach(obj=>obj.classList.remove("hover"));

For ES6, this can be done in a few ways with one liners, where you create an array of the elements with the spread operator ..., and remove the class with the map operator:

With querySelectorAll:

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

With getElementsByClassName:

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

For querySelectorAll, notice the use of .widget instead of widget. An alternative for the spread operator would be to use Array.from like:

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


for(let elem of elems){
elem.classList.remove('hover');
}

I use a simple method. If you always process [0] in the required number of loops, you can apply the process to all.

The HTMLCollection(elements) changes in real time, so put the length in a variable. (l = element.length)

for(var elements = document.getElementsByClassName('widget hover'), i = 0, l = elements.length; l > i; i++) {
elements[0].classList.remove("hover");
}