如何仅使用 DOM 将所有元素上的一个类替换为另一个类? [英] How can I replace one class with another on all elements, using just the DOM?

查看:17
本文介绍了如何仅使用 DOM 将所有元素上的一个类替换为另一个类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我试过使用

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

但它不起作用.我是 JavaScript 新手.

解决方案

说明

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

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

来自 MDN 文档的精彩描述:

<块引用>

HTML DOM 中的 HTMLCollections 是实时的;当基础文档发生变化时,它们会自动更新.

方法一

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

var els = document.getElementsByClassName('current'),i = els.length;当我 - ) {els[i].className = '无';}

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

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

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

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

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

方法 2

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

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

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

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

方法 3

另一种选择是将集合slice(浅拷贝)放入一个数组中并正常循环.但我认为没有任何理由/改进可以做到这一点.无论如何,这是一个示例:

var els = document.getElementsByClassName('current'),切片 = 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'),一世;for (i = 0; i < els.length; i++) {els[i].className = '无';}

演示: http://jsfiddle.net/xq8Xr/><小时>

参考:

I just want to change a classname to another one.

I've tried using

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

but it doesn't work. I'm new at javascript.

解决方案

Explanation

document.getElementsByClassName returns an HTMLCollection, not just an array of elements. That means that the collection is live, so in this specific situation, it retains the requirement that it will always hold all elements with the class "current".

Coincidentally, you are removing the very class that the collection depends on, therefore updating the collection. It would be totally different if you were setting the value property (for example) in the loop - the collection wouldn't be affected, because the class "current" wasn't removed. It would also be totally different if you were adding a class, such as el.className += " none";, but that isn't the case.

A great description from the MDN docs:

HTMLCollections in the HTML DOM are live; they are automatically updated when the underlying document is changed.

Approach 1

An easy way to overcome all this pandemonium is by looping backwards.

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

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

DEMO: http://jsfiddle.net/fAJgT/

(the code in the demo has a setTimeout, simply so you can see the original border color at first, then after 1.5 seconds, see it change)

This works because it modifies the last item in the collection - when it is modified (and automatically removed), move onto the item before it. So it doesn't suffer any consequences of the automatic removal.

An alternate setup, doing the same thing, is:

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

Approach 2

Another answer made me realize you could just continually operate on the first item found. When you remove the specific class, the element is removed from the collection, so you're guaranteed that the first item is always a fresh item in the collection. Therefore, checking the length property should be a safe condition to check. Here's an example:

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

DEMO: http://jsfiddle.net/EJLXe/

This is basically saying "while there's still items in the collection, modify the first one (which will be removed after modified)". I really wouldn't recommend ever using that method though, because it only works specifically because you end up modifying the collection. This would infinitely loop if you were not removing the specific class, or with a normal array or a non-live collection (without spliceing).

Approach 3

Another option is to slice (shallow copy) the collection into an array and loop through that normally. But I don't see any reason/improvement to do that. Here's an example anyways:

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

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

DEMO: http://jsfiddle.net/LHe95/2/

Approach 4

Finally, you could use document.querySelector - it returns a non-live NodeList (therefore you can loop like normal), and even has better support in browsers than document.getElementsByClassName does. Here's an example:

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

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

DEMO: http://jsfiddle.net/xq8Xr/


References:

这篇关于如何仅使用 DOM 将所有元素上的一个类替换为另一个类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆