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

Александр Мальцев
37K
2
2
Поиск элементов документа в JavaScript
Содержание:
  1. Методы JavaScript для выбора DOM элементов
  2. querySelectorAll – поиск элементов по CSS селектору
  3. querySelector – выбор элемента по CSS селектору
  4. «Старые» методы для выбора элементов
  5. Дополнительные материалы
  6. Задачи
  7. Комментарии

В этой статье мы рассмотрим какие в 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 селектору, но в отличие от него возвращает не все найденные элементы, а только первый из них.

Синтаксис:

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

В приведённом коде selector – это строка, содержащая CSS селектор, в соответствии с которым необходимо найти элемент.

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

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

Примеры

1. Обратиться к элементу по id, значение которого равно pagetitle:

var pagetitle = document.querySelector('#pagetitle');

2. Выполнить поиск элемента по классу nav:

var el = document.querySelector('.nav');

3. Обратиться к элементу <h3>, находящемуся в теге <div> с классом comments, который в свою очередь расположен в <main>:

var 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 
var 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 можно более эффективно:

var 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 можно решить так:

var 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 можно следующим образом:

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

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

Методы getElementsBy* в отличие от querySelectorAll возвращают живую коллекцию элементов. Т.е. коллекцию содержимое которой может изменяться при изменении DOM. Рассмотрим это на примере.

В этом примере получим элементы li находящиеся в #list и выведем их количество в консоль. Затем через 5 секунд программно добавим ещё один элемент li в #list и ещё раз возвратим их количество в консоль.

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

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

  // выведем количество элементов в коллекции elements в консоль
  console.log('Количество элементов в list: ' + elements.length); // 2
  // выполним код через 5 секунд
  setTimeout(function () {
    // cоздадим элемент 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>
  var
    // выберем элемент #list
    list = document.getElementById('list'),
    // получим статичную коллекцию elements состоящую из элементов li, расположенных в list
    elements = list.querySelectorAll('li');

  // выведем количество элементов в коллекции elements в консоль
  console.log('Количество элементов в list: ' + elements.length); // 2
  // выполним код через 5 секунд
  setTimeout(function () {
    // cоздадим элемент li с контентом "..."
    var 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>
  var
    // выберем элемент #list
    list = document.getElementById('list'),
    // получим статичную коллекцию elements состоящую из элементов li, расположенных в list
    elements = list.querySelectorAll('li');

  // выведем количество элементов в коллекции elements в консоль
  console.log('Количество элементов в list: ' + elements.length); // 2
  // выполним код через 5 секунд
  setTimeout(function () {
    // cоздадим элемент li с контентом "..."
    var 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>

Итого

В JavaScript можно выделить 6 основных методов для выбора элементов на странице.

Некоторые из них можно использовать для поиска одних элементов внутри других. Среди них: querySelector, querySelectorAll, getElementsByTagName, getElementsByClassName. Другие (getElementById и getElementsByName) можно применять только для выбора элементов в пределах всей страницы (document).

Кроме этого, их можно ещё дополнительно разделить на 2 группы. К первой группе можно отнести методы, которые возвращают статическую коллекцию элементов. Это querySelector, querySelectorAll и getElementById. Ко второй те методы, которые возвращаю живую коллекцию. Это getElementsByTagName, getElementsByClassName и getElementsByName.

Дополнительные материалы

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

matches – это метод, который проверяет соответствует элемент, для которого он вызывается указанному CSS селектору. Если соответствует, то возвращает true. В противном случае false.

Синтаксис:

var result = element.matches(selector);

Ранее, в «старых» браузерах данный метод имел название matchesSelector, а также поддерживался с префиксами.

Чтобы обеспечить поддержку данного метода большим количеством браузеров можно использовать следующий полифилл:

if (!Element.prototype.matches) {
  Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector;
}

Например, выберем все элементы <li> расположенные внутри элемента с id="questions", а затем удалим из них те, которые соответствуют селектору .answered:

// выберем все элементы <li> находящиеся в #questions
var questions = document.querySelectorAll('#questions > li');
// переберём выбранные элементы с помощью цикла for
for (var i = 0, len = questions.length; i < len; i++) {
  // если элемент можно получить с помощью селектора .answered, то...
  if (questions[i].matches('.answered')) {
    // удаляем его
    questions[i].remove();
  }
}

closest – поиск ближайшего предка по CSS селектору

closest – это метод, который позволяет найти ближайшего предка для элемента в соответствии с указанным селектором. При этом поиск предков начинается с самого элемента, для которого данный метод вызывается и если он будет ему соответствовать, то closest вернёт сам этот элемент.

Синтаксис:

var parent = someElement.closest(selector);

В приведённом коде selector – это строка, содержащая селектор, в соответствии с которым необходимо найти ближайшего предка для someElement.

В качестве результата метод closest возвращает найденный DOM-элемент или null (если соответствующий элемент найден не был).

Например, найдем для некоторого элемента ближайшего предка по селектору .parent:

<div class="parent">
  <div class="wrapper">
    <div id="child">...</div>
  </div>
</div>

<script>
  var child = document.querySelector('#child');
  var parent = child.closest('.parent'); // closest вернёт <div class="parent">
</script>

contains – проверка наличия одного элемента внутри другого

contains – это метод, посредством которого можно проверить существование одного элемента внутри другого.

Синтаксис:

var result = element1.contains(element2);

В приведённом коде result – это переменная, в которую поместится значение true или false в зависимости от того имеется ли element2 внутри element1.

Например:

<div id="parent">
  <div id="child">...</div>
</div>

<script>
  var parent = document.querySelector('#parent');
  var child = document.querySelector('#child');
  var result = parent.contains(child); // true
</script>

Задачи

Имеется страница. В ней следует выбрать:

  • последний элемент с классом article, расположенный в <main> (решение);
  • все элементы .section, находящиеся в .aside кроме 2 второго (решение);
  • элемент <nav> расположенный после <header> (решение).

Комментарии:

  1. Evgen
    27 апреля 2021, 17:48
    Добрый день!
    Перебор элементов посредством цикла for...of:
    // например, переберём все элементы html страницы (в CSS для выбора всех элементов используется символ *)
    // выберем все изображения на странице
    const all = document.querySelectorAll('*');
    // выведем все найденные DOM элементы в консоль
    for (let elem of all) {
      console.log(elem);
    }
    Наверное опечатка и нужно // выберем все ЭЛЕМЕНТЫ на странице?
    1. Денис
      30 апреля 2016, 19:20
      Благодарю за информацию!
      Навела на мысль, что поиск соседних элементов у родителя можно сделать ещё проще. И самое приятное, что работает!
      Долгое время не занимался темой, порядком подзабыл некоторые детали, тут прямо как раз то, что нужно.
      Войдите, пожалуйста, в аккаунт, чтобы оставить комментарий.