DOM, часть 3 из 3. Поиск элементов
09.05.2022
Теги: DOM • Frontend • HTML • JavaScript • Web-разработка • Документ • Коллекция • Теория
Свойства навигации по DOM хороши, когда элементы расположены рядом. А что, если нет? Как получить произвольный элемент страницы? Для этого в DOM есть дополнительные методы поиска — getElementById
, getElementsByTagName
, getElementsByClassName
, querySelector
, querySelectorAll
.
document.getElementById
Если у элемента есть атрибут id
, то мы можем получить его вызовом document.getElementById(id)
, где бы он ни находился.
<div id="elem">Какой-то контент</div> <script> // получить элемент let elem = document.getElementById('elem'); // сделать фон красным elem.style.background = 'red'; </script>
getElementById
можно вызвать только для объекта document
. Он осуществляет поиск по id
по всему документу.
elem.querySelectorAll
Самый универсальный метод поиска — это elem.querySelectorAll(css)
, он возвращает все элементы внутри elem
, удовлетворяющие данному CSS-селектору.
<ul> <li>Этот</li> <li>тест</li> </ul> <ul> <li>полностью</li> <li>пройден</li> </ul> <script> let elements = document.querySelectorAll('ul > li:last-child'); for (let elem of elements) { alert(elem.textContent); // тест, пройден } </script>
elem.querySelector
Метод elem.querySelector(css)
возвращает первый элемент внутри elem
, соответствующий данному CSS-селектору. Иначе говоря, результат такой же, как при вызове elem.querySelectorAll(css)[0]
, но он сначала найдёт все элементы, а потом возьмёт первый, в то время как elem.querySelector
найдёт только первый и остановится. Это быстрее, кроме того, его короче писать.
elem.closest
Предки элемента — это родитель, родитель родителя, его родитель и так далее. Вместе они образуют цепочку иерархии от элемента до вершины. Метод elem.closest(css)
ищет ближайшего предка, который соответствует CSS-селектору. Сам элемент также включается в поиск.
Другими словами, метод closest
поднимается вверх от элемента и проверяет каждого из родителей. Если он соответствует селектору, поиск прекращается. Метод возвращает либо предка, либо null
, если такой элемент не найден.
<h1>Содержание</h1> <div class="contents"> <ul class="book"> <li class="chapter">Глава 1</li> <li class="chapter">Глава 2</li> </ul> </div> <script> let chapter = document.querySelector('.chapter'); // <li class="chapter">Глава 1</li> alert(chapter.closest('.book')); // <ul class="book"> alert(chapter.closest('.contents')); // <div class="contents"> alert(chapter.closest('h1')); // null (потому что h1 — не предок) </script>
elem.matches
Предыдущие методы искали по DOM. Метод elem.matches(css)
ничего не ищет, а проверяет, удовлетворяет ли elem
CSS-селектору, и возвращает true
или false
. Метод удобен, когда мы перебираем элементы (например, в массиве) и пытаемся выбрать те из них, которые нас интересуют.
<a href="http://example.com/file.zip">...</a> <a href="http://yandex.ru">...</a> <script> // может быть любая коллекция вместо document.body.children for (let elem of document.body.children) { if (elem.matches('a[href$="zip"]')) { alert('Ссылка на архив: ' + elem.href); } } </script>
elem.contains
Метод elem.contains(node)
возвращает логическое значение, указывающее, является ли node
потомком elem
, то есть сам узел, один из его прямых потомков, один из детей его детей и так далее.
elem.getElementsByTagName
Метод elem.getElementsByTagName(tag)
ищет элементы с данным тегом и возвращает их коллекцию. Передав *
вместо тега, можно получить всех потомков.
elem.getElementsByClassName
Метод elem.getElementsByClassName(className)
возвращает элементы, которые имеют данный CSS-класс.
Живые коллекции
Методы getElementsByTagName
и getElementsByClassName
возвращают живую коллекцию. Такие коллекции всегда отражают текущее состояние документа и автоматически обновляются при его изменении.
<div>Первый div</div> <script> let divs = document.getElementsByTagName('div'); alert(divs.length); // 1 </script> <div>Второй div</div> <script> alert(divs.length); // 2 </script>
Напротив, querySelectorAll
возвращает статическую коллекцию. Это похоже на фиксированный массив элементов.
<div>Первый div</div> <script> let divs = document.querySelectorAll('div'); alert(divs.length); // 1 </script> <div>Второй div</div> <script> alert(divs.length); // 1 </script>
Длина статической коллекции не изменилась после появления нового div
в документе.
HTMLCollection и NodeList
HTMLCollection
и NodeList
— это очень похожие на массив коллекции. Они хранят элементы веб-страницы (узлы DOM). NodeList
может хранить любые типы узлов, а HTMLCollection
— только узлы HTML элементов. К элементам коллекций можно обращаться по индексу, но у них нет привычных методов массива.
HTMLCollection
возвращают методыgetElementsByTagName
,getElementsByClassName
и свойствоchildren
NodeList
возвращают методыquerySelectorAll
,getElementsByName
и свойствоchildNodes
Полученная один раз HTMLCollection
всегда остаётся актуальной — поэтому ее часто называют «живой» коллекцией. Это значит, что JavaScript будет обновлять её в случае, если на странице появляется новый подходящий элемент.
NodeList
может быть не только «живой» коллекцией, но и статической. Такая коллекция не обновляется при появлении на странице новых элементов. «Живой» NodeList
возвращают метод getElementsByName
и свойство childNodes
. Метод querySelectorAll
возвращает статический NodeList
.
- DOM, часть 1 из 3. Навигация по элементам
- DOM, часть 4 из 4. Атрибуты и свойства
- DOM, часть 2 из 3. Изменение документа
- JavaScript. HTMLCollection и NodeList
- Браузерные события, часть 5 из 5. Генерация пользовательских событий
- Браузерные события, часть 4 из 5. Действие браузера по умолчанию
- Браузерные события, часть 3 из 5. Делегирование
Поиск: DOM • Frontend • HTML • JavaScript • Web-разработка • Документ • Коллекция • Теория