Можно ли получить все элементы с классом a
или b
с помощью getElementsByClassName()
только один раз? Я бы предпочел ванильный JavaScript.
GetElementsByClassName() с двумя классами
Ответ 1
Вы не можете сделать это с помощью getElementsByClassName()
вместо этого используйте querySelectorAll()
с селекторами разделенных запятыми.
document.querySelectorAll('.a,.b')
Ответ 2
Чтобы добавить немного больше поддержки, вот версия, совместимая со старыми версиями IE и использующая чистую ваниль 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.
}
Ответ 3
Нет, вы не можете добиться этого только одним вызовом document.getElementsByClassName()
. Эта функция возвращает элементы, которые имеют все классы, указанные в первом аргументе, в виде строки, разделенной пробелом.
Существует два возможных решения. Сначала следует использовать document.querySelectorAll()
, в котором используются селекторы CSS.
document.querySelectorAll(".a, .b")
Второе решение состоит в том, чтобы дважды вызвать document.getElementsByClassName()
, превратить результаты в массивы, используя Array.from()
и объединить их с помощью Array.prototype.concat()
. Чтобы избежать дублирования (например, когда элемент имеет как a
, так и b
класс), вам необходимо создать новый Set из этот массив, а затем верните его в массив с помощью Array.from()
.
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>
Ответ 4
Вы можете передать более одного имени класса в getElementsByClassName()
, разделив их пробелами:
var elems = document.getElementsByClassName("class1 class2 class3");
Теперь это отличается от подхода .querySelectorAll(".class1,.class2,.class3")
тем, что он применяет конъюнкцию, а не дизъюнкцию — "и" вместо "или". Таким образом,
var elems = document.getElementsByClassName("class1 class2 class3");
похож на
var elems = document.querySelectorAll(".class1.class2.class3");
Иногда вам нужен один, иногда вам нужен другой. Это определенно верно, что .querySelectorAll()
дает вам гораздо большую гибкость.