getElementsBy*
Существуют также другие методы поиска элементов по тегу, классу и так далее.
На данный момент, они скорее исторические, так как querySelector
более чем эффективен.
Здесь мы рассмотрим их для полноты картины, также вы можете встретить их в старом коде.
elem.getElementsByTagName(tag)
ищет элементы с данным тегом и возвращает их коллекцию. Передав"*"
вместо тега, можно получить всех потомков.elem.getElementsByClassName(className)
возвращает элементы, которые имеют данный CSS-класс.document.getElementsByName(name)
возвращает элементы с заданным атрибутомname
. Очень редко используется.
Например:
// получить все элементы div в документе
let divs = document.getElementsByTagName('div');
Давайте найдём все input
в таблице:
<table id="table">
<tr>
<td>Ваш возраст:</td>
<td>
<label>
<input type="radio" name="age" value="young" checked> младше 18
</label>
<label>
<input type="radio" name="age" value="mature"> от 18 до 50
</label>
<label>
<input type="radio" name="age" value="senior"> старше 60
</label>
</td>
</tr>
</table>
<script>
let inputs = table.getElementsByTagName('input');
for (let input of inputs) {
alert( input.value + ': ' + input.checked );
}
</script>
Не забываем про букву "s"
!
Одна из самых частых ошибок начинающих разработчиков (впрочем, иногда и не только) – это забыть букву "s"
. То есть пробовать вызывать метод getElementByTagName
вместо getElementsByTagName
.
Буква "s"
отсутствует в названии метода getElementById
, так как в данном случае возвращает один элемент. Но getElementsByTagName
вернёт список элементов, поэтому "s"
обязательна.
Возвращает коллекцию, а не элемент!
Другая распространённая ошибка – написать:
// не работает
document.getElementsByTagName('input').value = 5;
Попытка присвоить значение коллекции, а не элементам внутри неё, не сработает.
Нужно перебрать коллекцию в цикле или получить элемент по номеру и уже ему присваивать значение, например, так:
// работает (если есть input)
document.getElementsByTagName('input')[0].value = 5;
Ищем элементы с классом .article
:
<form name="my-form">
<div class="article">Article</div>
<div class="long article">Long article</div>
</form>
<script>
// ищем по имени атрибута
let form = document.getElementsByName('my-form')[0];
// ищем по классу внутри form
let articles = form.getElementsByClassName('article');
alert(articles.length); // 2, находим два элемента с классом article
</script>
Живые коллекции
Все методы "getElementsBy*"
возвращают живую коллекцию. Такие коллекции всегда отражают текущее состояние документа и автоматически обновляются при его изменении.
В приведённом ниже примере есть два скрипта.
- Первый создаёт ссылку на коллекцию
<div>
. На этот момент её длина равна1
. - Второй скрипт запускается после того, как браузер встречает ещё один
<div>
, теперь её длина –2
.
<div>First div</div>
<script>
let divs = document.getElementsByTagName('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
alert(divs.length); // 2
</script>
Напротив, querySelectorAll
возвращает статическую коллекцию. Это похоже на фиксированный массив элементов.
Если мы будем использовать его в примере выше, то оба скрипта вернут длину коллекции, равную 1
:
<div>First div</div>
<script>
let divs = document.querySelectorAll('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
alert(divs.length); // 1
</script>
Теперь мы легко видим разницу. Длина статической коллекции не изменилась после появления нового div
в документе.
Итого
Есть 6 основных методов поиска элементов в DOM:
Метод | Ищет по… | Ищет внутри элемента? | Возвращает живую коллекцию? |
querySelector | CSS-selector | ✔ | – |
querySelectorAll | CSS-selector | ✔ | – |
getElementById | id | – | – |
getElementsByName | name | – | ✔ |
getElementsByTagName | tag or '*' | ✔ | ✔ |
getElementsByClassName | class | ✔ | ✔ |
Безусловно, наиболее часто используемыми в настоящее время являются методы querySelector
и querySelectorAll
, но и методы getElement(s)By*
могут быть полезны в отдельных случаях, а также встречаются в старом коде.
Кроме того:
- Есть метод
elem.matches(css)
, который проверяет, удовлетворяет ли элемент CSS-селектору. - Метод
elem.closest(css)
ищет ближайшего по иерархии предка, соответствующему данному CSS-селектору. Сам элемент также включён в поиск.
И, напоследок, давайте упомянем ещё один метод, который проверяет наличие отношений между предком и потомком:
elemA.contains(elemB)
вернётtrue
, еслиelemB
находится внутриelemA
(elemB
потомокelemA
) или когдаelemA==elemB
.