Поиск элементов документа в JavaScript

В этой статье мы рассмотрим какие в JavaScript существуют методы для выбора элементов на странице, и как с ними работать.

Методы JavaScript для выбора DOM элементов

Работа со страницей так или иначе связана с манипулированием DOM элементами. Но перед тем, как это делать их сначала нужно получить.

Выполняется это в JavaScript посредством специальных методов. Наиболее популярные из них – это querySelectorAll и querySelector. Данные методы осуществляют поиск элементов по CSS селектору.
Их отличие сводится в различии количества возвращаемых DOM элементов. Первый (querySelectorAll) возвращает все найденные элементы, а второй (querySelector) – только первый из них.
Кроме них, в DOM API существуют ещё getElementById, getElementsByClassName, getElementsByTagName и getElementsByName. Сейчас они применяются крайне редко, в основном все выполняется через querySelectorAll и querySelector.

querySelectorAll – поиск элементов по CSS селектору

querySelectorAll – применяется, когда нужно найти все элементы по CSS селектору внутри страницы или определённого элемента.

Синтаксис:

// elements1, elements2 – переменные, в которые будут помещены коллекции найденных элементов

// поиск внутри всего документа
const elements1 = document.querySelectorAll('css_selector');
// поиск внутри элемента (elem)
const elements2 = elem.querySelectorAll('css_selector');

В приведённом коде css_selector – это строка, содержащая CSS селектор, в соответствии с которым необходимо осуществить поиск элементов.
querySelectorAll возвращает все найденные элементы в виде статической коллекции типа NodeList.
Статическая коллекция — это такая, которая не изменяется, если после вызова этого метода на странице появились новые элементы, подходящие под указанный CSS селектор. В этом случае, чтобы в сформированную коллекцию попали новые элементы их выбор нужно выполнить заново.
Узнать количество элементов в коллекции можно с помощью свойства length:

// выберем все элементы с type="submit" на странице
const submitList = document.querySelectorAll('[type="submit"]');
// узнаем количество найденных элементов
const submitLength = submitList.length;

Обратиться к определённому элементу в коллекции можно по его индексу. Индексы начинаются с 0.

// получим первый элемент из submitList
const submit1 = submitList[0];
// получим второй элемент из submitList
const submit2 = submitList[1];

В этом случае возвращается DOM элемент находящийся под указанным индексом в коллекции или undefined, если элемента с таким индексом нет.
Перебрать коллекцию выбранных элементов можно с помощью цикла for:

// получим все элементы p на странице
const paragraphList = document.querySelectorAll('p');
// переберём полученную коллекцию элементов с помощью цикла for
for (let i=0, length = paragraphList.length; i < length; i++) { // paragraphList[i] - i-ый элемент }

Перебор элементов посредством цикла for...of:

// например, переберём все элементы html страницы (в CSS для выбора всех элементов используется символ *)
// выберем все изображения на странице
const all = document.querySelectorAll('*');
// выведем все найденные DOM элементы в консоль
for (let elem of all) {
console.log(elem);
}

Примеры

1.
//Выполним проверку существование элементов с атрибутом data-toggle="modal":
if (document.querySelectorAll('[data-toggle="modal"]').length) {
// на странице данные элементы есть в наличии
}
2.
//Найти все элементы <a> внутри элемента <ul> с классом nav:
const anchors = document.querySelectorAll('ul.nav a');

querySelector – выбор элемента по CSS селектору

querySelector – это метод, который также как querySelectorAll осуществляет поиск по CSS селектору, но в отличие от него возвращает не все найденные элементы, а только первый из них.

Синтаксис:

// поиск внутри всего документа
let element = document.querySelector('selector');
// поиск внутри конкретного элемента (elem)
let element = elem.querySelector('selector');

В приведённом коде selector – это строка, содержащая CSS селектор, в соответствии с которым необходимо найти элемент.
Результат метода querySelector аналогичен elem.querySelectorAll('selector')[0], но в отличие от него он выполняет это намного быстрее. Это происходит потому, что querySelector сразу же останавливает процесс поиска, как только находит соответствующий элемент. В то время как elem.querySelectorAll('selector')[0] сначала находит все элементы, и только после того как он все их нашёл мы уже можем обратиться к этим элементам и с помощью оператора доступа (квадратные скобки) взять первый из них.

В качестве результата метод querySelector возвращает ссылку на объект типа Element или null (если элемент не найден).

Примеры

1.
//Обратиться к элементу по id, значение которого равно pagetitle:
let pagetitle = document.querySelector('#pagetitle');
2.
//Выполнить поиск элемента по классу nav:
let el = document.querySelector('.nav');
3.
//Обратиться к элементу <h3>, находящемуся в теге <div> с классом comments, который в свою очередь расположен в <main>:
let header = document.querySelector('main div.comments h3');
4.
//Проверить наличие элемента с классом modal на странице:
if (document.querySelector('.modal')) {
// элемент .modal существует
}

«Старые» методы для выбора элементов

К данной категории относятся методы, которые сейчас практически не применяются для поиска элементов. Их в основном можно встретить в «старом» коде.
getElementById – предназначен для получения элемента по id (идентификатору);
getElementsByClassName – используется, когда нужно найти элемент по одному или нескольким классам;
getElementsByTagName – применяется для выбора элементов по тегу;
getElementsByName – прибегают, когда следует обратиться к элементам по атрибуту name.

getElementById – получение элемента по значению id

Например:

<div id="main">...</div>

<script>
// получим элемент и сохраним ссылку на него в переменную main
var main = document.getElementById('main');
</script>

В качестве результата метод getElementById возвращает ссылку на объект типа Element или значение null, если элемент с указанным идентификатором не найден.
Метод getElementById имеется только у объекта document.
Указания значения id необходимо выполнять с учётом регистра, т.к., например, main и Main – это разные значения.
Кроме этого, в соответствии со стандартом в документе не может быть несколько элементов с одинаковым значением атрибута id, т.к. значение идентификатора должно быть уникальным.
Тем не менее, если вы допустили ошибку и в документе существуют несколько элементов с одинаковым id, то метод getElementById более вероятно вернёт первый элемент, который он встретит в коде (DOM). Но на это полагаться нельзя, т.к. такое поведение не прописано в стандарте.

Например, получим элемент, имеющий в качестве id значение pagetitle:

<h1 id="pagetitle">Название статьи</h1>

<script>
// получим элемент, имеющий id="pagetitle"
var pagetitle = document.getElementById('pagetitle');
</script>>

Действие метода getElementById можно очень просто выполнить с помощью querySelector:

// получение элемента #nav через getElementById
var nav = document.getElementById('nav');
// получение элемента #nav через querySelector
let nav = document.querySelector('#nav');

getElementsByClassName – получение списка элементов по именам классов

Этот метод позволяет найти все элементы с указанными классами во всём документе или в некотором элементе. В первом случае его необходимо вызывать у document, а во втором – у элемента, внутри которого вы хотите их получить.

Синтаксис:

// внутри всего документа
var elements = document.getElementsByClassName(names);
// внутри некоторого элемента (someElement)
var elements = someElement.getElementsByClassName(names);

в переменную elements будет помещена живая коллекция (HTMLCollection) найденных элементов;
в names необходимо задать строку, состоящую из одного или нескольких классов разделённых между собой с помощью пробела.
Например, получим все элементы с классом btn, которые имеются на странице:

var btns = document.getElementsByClassName('btn');

Метод getElementsByClassName позволяет искать элементы не только по одному имени класса, но и по нескольким, которые должны быть у элемента.
Например, выберем элементы на странице у которых имеются классы btn и btn-danger:

var elements = document.getElementsByClassName('btn btn-danger');

Функция getElementsByClassName позволяет искать элементы не только внутри всего документа, но и в конкретном элементе.
Например, найти все элементы с классом code, расположенные внутри элемента #main:

// получение элемента с id='main'
var main = document.getElementsById('main');
// получим все элементы с классом code, расположенные в #main
var codes = main.getElementsByClassName('code');

Выполнить эту задачу с помощью querySelectorAll можно более эффективно:

let codes = document.querySelectorAll('#main .code');

getElementsByTagName – получение элементов по имени тега

Метод getElementsByTagName предназначен для получения коллекции элементов по имени тега.

Синтаксис:

// внутри всего документа
var elements = element.getElementsByTagName(tagName);
// внутри некоторого элемента (someElement)
var elements = someElement.getElementsByTagName(tagName);

tagName - это аргумент, который должен содержать строку с названием тега, который нужно найти. Название тега необходимо указывать с помощью прописных букв. Чтобы выбрать все элементы можно использовать символ *.
Например, получить коллекцию элементов <li>, находящихся в элементе с id="aside__nav":

// получим элемент с id="aside__nav"
var asideNav = element.getElementById('aside__nav');
// получим li расположенные внутри элемента asideNav
var elements = asideNav.getElementsByTagName('li');

Этот пример через querySelectorAll можно решить так:

let elements = document.querySelectorAll('#aside__nav li');

getElementsByName – получение элементов по значению атрибута name

Метод getElementsByName может применяться, когда вам нужно выбрать элементы, имеющие атрибут nameс указанным значением.

Синтаксис:

// внутри всего документа
var elements = element.getElementsByName(name);
// внутри некоторого элемента (someElement)
var elements = someElement.getElementsByName(name);

name - это аргумент, содержащий строку со значением атрибута name в соответствии с которым нужно найти элементы.
Например, выбрать все элементы на странице с name="phone":

var phoneList = document.getElementsByName('phone');

Реализовать это с querySelectorAll можно следующим образом:

let phoneList = document.querySelectorAll('[name="phone"]');

getElementsBy* и живые коллекции

Методы getElementsBy* в отличие от querySelectorAll возвращают живую коллекцию элементов. Т.е. коллекцию содержимое которой может изменяться при изменении DOM. Рассмотрим это на примере.
В этом примере получим элементы li находящиеся в #list и выведем их количество в консоль. Затем через 5 секунд программно добавим ещё один элемент li в #list и ещё раз возвратим их количество в консоль.

<ul id="list">
<li>...</li>
<li>...</li>
</ul>

<script>
// выберем элемент #list
var list = document.getElementById('list'),
// получим живую коллекцию elements состоящую из элементов li, расположенных в list
elements = list.getElementsByTagName('LI');

// выведем количество элементов в коллекции elements в консоль
console.log('Количество элементов в list: ' + elements.length); // 2
// выполним код через 5 секунд
setTimeout(function () {
// создадим элемент li с контентом "..."
var li = document.createElement('LI');
li.textContent = '...';
// добавим его в #list
list.append(li);
// выведем количество элементов в коллекции elements в консоль
console.log('Количество элементов в list: ' + elements.length); // 3
}, 5000);
</script>

Как вы видите, эта коллекция элементов является живой, т.е. она автоматически изменяется. Сначала в ней было 2 элемента, а после того, как мы на страницу добавили ещё один подходящий элемент, в ней их стало 3.
Если тоже выполнить с помощью querySelectorAll, то мы увидим, что в ней находится статическая (не живая) коллекция элементов.

<ul id="list">
<li>...</li>
<li>...</li>
</ul>

<script>
// выберем элемент #list
let list = document.getElementById('list'),
// получим статичную коллекцию elements состоящую из элементов li, расположенных в list
elements = list.querySelectorAll('li');

// выведем количество элементов в коллекции elements в консоль
console.log('Количество элементов в list: ' + elements.length); // 2
// выполним код через 5 секунд
setTimeout(function () {
// cоздадим элемент li с контентом "..."
let li = document.createElement('LI');
li.textContent = '...';
// добавим его в #list
list.append(li);
// выведем количество элементов в коллекции elements в консоль
console.log('Количество элементов в list: ' + elements.length); // 2
}, 5000);
</script>

Как вы видите количество элементов в коллекции не изменилось.
Если вам нужно обновить статическую коллекцию элементов после изменения DOM, то метод querySelectorAll нужно вызвать ещё раз.

<ul id="list">
<li>...</li>
<li>...</li>
</ul>

<script>
// выберем элемент #list
let list = document.getElementById('list'),
// получим статичную коллекцию elements состоящую из элементов li, расположенных в list
elements = list.querySelectorAll('li');

// выведем количество элементов в коллекции elements в консоль
console.log('Количество элементов в list: ' + elements.length); // 2
// выполним код через 5 секунд
setTimeout(function () {
// cоздадим элемент li с контентом "..."
let li = document.createElement('LI');
li.textContent = '...';
// добавим его в #list
list.append(li);
// получим статичную коллекцию elements состоящую из элементов li, расположенных в list
elements = list.querySelectorAll('li');
// выведем количество элементов в коллекции elements в консоль
console.log('Количество элементов в list: ' + elements.length); // 3
}, 5000);
</script>

Обсуждение закрыто.