getElementsByClassName() 有两个类

Posted

技术标签:

【中文标题】getElementsByClassName() 有两个类【英文标题】:getElementsByClassName() with two classes 【发布时间】:2016-09-12 07:46:42 【问题描述】:

是否有可能只使用一次getElementsByClassName() 获得所有具有类a b 的元素?我更喜欢原生 javascript

【问题讨论】:

【参考方案1】:

您不能使用 getElementsByClassName() 方法来代替使用带有逗号分隔的类选择器的 querySelectorAll() 方法。

document.querySelectorAll('.a,.b')

【讨论】:

这是正确的答案,但请注意,对 IE8 的支持仅适用于 CSS2 选择器,不支持 IE 我看到你的编辑,但 getElementsByClassName 在 IE @zoubida13:.a,.b 怎么不只是两个 CSS2 选择器? @zoubida13 : 我认为没有人还在使用IE <= 7 :) ;) 连微软都不支持IE7了。为什么公司或开发人员仍然这样做,我无法理解!【参考方案2】:

可以通过用空格分隔多个类名给getElementsByClassName()

var elems = document.getElementsByClassName("class1 class2 class3");

现在,这与.querySelectorAll(".class1,.class2,.class3") 方法的不同之处在于它应用了连词,而不是连词——“and”而不是“or”。因此

var elems = document.getElementsByClassName("class1 class2 class3");

就像

var elems = document.querySelectorAll(".class1.class2.class3");

有时你想要一个,有时你想要另一个。 .querySelectorAll() 确实为您提供了更大的灵活性。

【讨论】:

这是不对的。它将搜索具有所有三个类的元素 这是一个“与”而不是“或” @epascarello 是的,我明白了;这只是一个答案。 这个答案不起作用。它只会返回所有指定类的元素。 这是一个回答错误问题的答案,提供的信息与所提出的问题并不完全相关。而且很可能是 OP 已经知道的事情。因此,这主要是噪音。【参考方案3】:

只是为了增加一点支持,这里是一个兼容旧版本 IE 并使用纯 vanilla js 的版本:

function getElementsByClassNameOr(root, classNameString) // classNameString like '.a, .b' don't forget the comma separator
 
    var arr = [],
    rx = new RegExp('(^|[ \n\r\t\f])' + classNameString + '([ \n\r\t\f]|$)'),
    elements = root.getElementsByTagName("*");

    var elem;

    for (i=0 ; i < elements.length ; i++) 
        elem = elements[i];
        if (rx.test(elem.className)) 
            arr.push(elem);
        

    

    return arr; // will contain all the elements that have one of the classes in ClassNameString, root can be document or a div.

【讨论】:

这将非常低效。请注意,通过支持较旧的浏览器,一个目标是much slower 浏览器。在这种情况下,性能至关重要,我建议多次调用 Element.getElementsByClassName 并使用结果的串联数组。 @Tim 您对性能的看法是正确的,尽管性能在这种情况下至关重要这一事实完全取决于您的解释。而且您的建议既不有效也不详细。 IE @zoubida13 你完全正确。似乎没有比这个答案更好的方法了。 @Blender 我用分号替换了逗号,确实是错字。 @zoubida13:您的代码假定类名彼此相邻,因此当您使用'a c' 搜索时,它不适用于class="a b c"【参考方案4】:

不,仅通过一次document.getElementsByClassName() 调用是无法实现的。该函数将具有 all 在第一个参数中指定的类的元素作为空格分隔的字符串返回。

有两种可能的解决方案。首先是使用 document.querySelectorAll() 代替,它使用 CSS 选择器。

document.querySelectorAll(".a, .b")

第二种解决方案是调用document.getElementsByClassName() 两次,使用Array.from() 将结果转换为数组,然后使用Array.prototype.concat() 将它们合并。为避免重复(例如,当元素 both ab 类时),您必须从该数组创建一个新的 Set,然后使用 @987654335 将其转回数组@。

const classA = Array.from(document.getElementsByClassName("a"))
     ,classB = Array.from(document.getElementsByClassName("b"))
     ,result = Array.from(new Set(classA.concat(classB)))

请看下面的演示:

console.log("first solution", document.querySelectorAll(".a, .b"))

const classA = Array.from(document.getElementsByClassName("a"))
     ,classB = Array.from(document.getElementsByClassName("b"))
     ,result = Array.from(new Set(classA.concat(classB)))

console.log("second solution", result)
<div class="a"></div>
<div class="b"></div>
<div class="a b"></div>
<div class="c"></div>

请注意,第一个解决方案给出了一个类似数组的 NodeList 对象,而第二个解决方案只给出了一个数组。

【讨论】:

使用Set是没有意义的,因为那些浏览器不支持,不支持querySelectorAll。 @Somnium 这并不像看起来那样毫无意义。 Babel 支持 Set,但不支持 document.querySelectorAll()(因为它不是 ECMAScript 的一部分,而是 Web API 的一部分)。如果你使用 Babel 编译你的代码,第二个解决方案将适用于所有浏览器。坦率地说,我写第二个解决方案是为了好玩,而不是真正的解决方案。 Array.from 在 Internet Explorer 11 中产生问题。

以上是关于getElementsByClassName() 有两个类的主要内容,如果未能解决你的问题,请参考以下文章

IE8 兼容 getElementsByClassName

兼容性比较好的getElementsByClassName函数

IE浏览器下getElementsByClassName()属性的使用

比较 document.getElementsByClassName().innerHTML 和 int

尝试 GetElementsByClassName [关闭]

JS兼容getElementsByClassName