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

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

问题描述

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



我尝试使用



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



但它不工作。我在javascript上是新的。

解决方案

说明



document.getElementsByClassName 返回一个 HTMLCollection ,而不仅仅是一个元素数组。这意味着收集是现场的,所以在这种具体情况下,它保留要求始终使用current类保持所有元素。



无意中,您正在删除集合所依赖的,因此更新集合。如果您在循环中设置值(例如),则完全不同 - 集合不会受到影响,因为current没有被删除。如果你是添加一个类,例如 el.className + =none; ,那么它也会完全不同案例。



MDN文档的一个很好的描述:


HTMLCollections in HTML DOM是活的;当基础文件更改时,它们将自动更新。




方法1



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

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

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

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



(演示中的代码有一个 setTimeout ,只需要先看到原始边框颜色,然后在1.5秒后看到它变化)



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



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


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



方法2



另一个答案让我意识到,你可以继续操作第一个找到的项目。当您删除特定的类时,元素将从集合中删除,因此您可以确保第一个项目始终是集合中的新项目。因此,检查长度属性应该是一个安全的检查条件。这里有一个例子:

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

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



这基本上是说while收藏中仍然有项目,修改第一个(修改后将被删除)。我真的不建议不要使用这种方法,因为它只起作用,特别是因为你最终修改集合。如果您没有删除特定类使用正常数组或非实时集合(无 splice ),这将无限循环



方法3



另一个选项是切片(浅拷贝)集合到一个数组中并循环通过。但是我没有看到任何理由/改进。这里有一个例子:

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

{
sliceed [i] .className ='none';
}

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



方法4



最后,您可以使用 document.querySelector - 它返回非活动 NodeList (因此您可以正常循环),甚至在浏览器中比 document.getElementsByClassName c $ c>。这是一个例子:

  var els = document.querySelectorAll('。current'),
i; (i = 0; i< els.length; i ++)

{
els [i] .className ='none';
}

演示: 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天全站免登陆