Как искать элементы в dom дереве
Перейти к содержимому

Как искать элементы в dom дереве

  • автор:

Поиск: getElement*, querySelector*

Свойства навигации по DOM хороши, когда элементы расположены рядом. А что, если нет? Как получить произвольный элемент страницы?

Для этого в DOM есть дополнительные методы поиска.

document.getElementById или просто id

Если у элемента есть атрибут id , то мы можем получить его вызовом document.getElementById(id) , где бы он ни находился.

Также есть глобальная переменная с именем, указанным в id :

…Но это только если мы не объявили в JavaScript переменную с таким же именем, иначе она будет иметь приоритет:

Пожалуйста, не используйте такие глобальные переменные для доступа к элементам

Это поведение соответствует стандарту, но поддерживается в основном для совместимости, как осколок далёкого прошлого.

Браузер пытается помочь нам, смешивая пространства имён JS и DOM. Это удобно для простых скриптов, которые находятся прямо в HTML, но, вообще говоря, не очень хорошо. Возможны конфликты имён. Кроме того, при чтении JS-кода, не видя HTML, непонятно, откуда берётся переменная.

В этом учебнике мы будем обращаться к элементам по id в примерах для краткости, когда очевидно, откуда берётся элемент.

В реальной жизни лучше использовать document.getElementById .

Значение id должно быть уникальным

Значение id должно быть уникальным. В документе может быть только один элемент с данным id .

Если в документе есть несколько элементов с одинаковым значением id , то поведение методов поиска непредсказуемо. Браузер может вернуть любой из них случайным образом. Поэтому, пожалуйста, придерживайтесь правила сохранения уникальности id .

Только document.getElementById , а не anyElem.getElementById

Метод getElementById можно вызвать только для объекта document . Он осуществляет поиск по id по всему документу.

querySelectorAll

Самый универсальный метод поиска – это elem.querySelectorAll(css) , он возвращает все элементы внутри elem , удовлетворяющие данному CSS-селектору.

Этот метод действительно мощный, потому что можно использовать любой CSS-селектор.

Псевдоклассы тоже работают

Псевдоклассы в CSS-селекторе, в частности :hover и :active , также поддерживаются. Например, document.querySelectorAll(‘:hover’) вернёт коллекцию (в порядке вложенности: от внешнего к внутреннему) из текущих элементов под курсором мыши.

querySelector

Метод elem.querySelector(css) возвращает первый элемент, соответствующий данному CSS-селектору.

Иначе говоря, результат такой же, как при вызове elem.querySelectorAll(css)[0] , но он сначала найдёт все элементы, а потом возьмёт первый, в то время как elem.querySelector найдёт только первый и остановится. Это быстрее, кроме того, его короче писать.

matches

Предыдущие методы искали по DOM.

Метод elem.matches(css) ничего не ищет, а проверяет, удовлетворяет ли elem CSS-селектору, и возвращает true или false .

Этот метод удобен, когда мы перебираем элементы (например, в массиве или в чём-то подобном) и пытаемся выбрать те из них, которые нас интересуют.

. .  

closest

Предки элемента – родитель, родитель родителя, его родитель и так далее. Вместе они образуют цепочку иерархии от элемента до вершины.

Метод elem.closest(css) ищет ближайшего предка, который соответствует CSS-селектору. Сам элемент также включается в поиск.

Другими словами, метод closest поднимается вверх от элемента и проверяет каждого из родителей. Если он соответствует селектору, поиск прекращается. Метод возвращает либо предка, либо null , если такой элемент не найден.

getElementsBy*

Существуют также другие методы поиска элементов по тегу, классу и так далее.

На данный момент, они скорее исторические, так как querySelector более чем эффективен.

Здесь мы рассмотрим их для полноты картины, также вы можете встретить их в старом коде.

  • elem.getElementsByTagName(tag) ищет элементы с данным тегом и возвращает их коллекцию. Передав «*» вместо тега, можно получить всех потомков.
  • elem.getElementsByClassName(className) возвращает элементы, которые имеют данный CSS-класс.
  • document.getElementsByName(name) возвращает элементы с заданным атрибутом name . Очень редко используется.
// получить все элементы div в документе let divs = document.getElementsByTagName('div');

Давайте найдём все input в таблице:

 
Ваш возраст:
let inputs = table.getElementsByTagName('input'); for (let input of inputs)

Не забываем про букву «s» !

Одна из самых частых ошибок начинающих разработчиков (впрочем, иногда и не только) – это забыть букву «s» . То есть пробовать вызывать метод getElementByTagName вместо getElementsByTagName .

Буква «s» отсутствует в названии метода getElementById , так как в данном случае возвращает один элемент. Но getElementsByTagName вернёт список элементов, поэтому «s» обязательна.

Возвращает коллекцию, а не элемент!

Другая распространённая ошибка – написать:

// не работает document.getElementsByTagName('input').value = 5;

Попытка присвоить значение коллекции, а не элементам внутри неё, не сработает.

Нужно перебрать коллекцию в цикле или получить элемент по номеру и уже ему присваивать значение, например, так:

// работает (если есть input) document.getElementsByTagName('input')[0].value = 5;

Ищем элементы с классом .article :

 
Long article

Живые коллекции

Все методы «getElementsBy*» возвращают живую коллекцию. Такие коллекции всегда отражают текущее состояние документа и автоматически обновляются при его изменении.

В приведённом ниже примере есть два скрипта.

  1. Первый создаёт ссылку на коллекцию . На этот момент её длина равна 1 .
  2. Второй скрипт запускается после того, как браузер встречает ещё один , теперь её длина – 2 .
First div
Second div

Напротив, querySelectorAll возвращает статическую коллекцию. Это похоже на фиксированный массив элементов.

Если мы будем использовать его в примере выше, то оба скрипта вернут длину коллекции, равную 1 :

First div
Second div

Теперь мы легко видим разницу. Длина статической коллекции не изменилась после появления нового 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 .

Задачи

Поиск элементов

важность: 4

Вот документ с таблицей и формой.

  1. Таблицу с id=»age-table» .
  2. Все элементы label внутри этой таблицы (их три).
  3. Первый td в этой таблице (со словом «Age»).
  4. Форму form с именем name=»search» .
  5. Первый input в этой форме.
  6. Последний input в этой форме.

Откройте страницу table.html в отдельном окне и используйте для этого браузерные инструменты разработчика.

Есть много путей как это сделать.

// 1. Таблица с `id="age-table"`. let table = document.getElementById('age-table') // 2. Все label в этой таблице table.getElementsByTagName('label') // или document.querySelectorAll('#age-table label') // 3. Первый td в этой таблице table.rows[0].cells[0] // или table.getElementsByTagName('td')[0] // или table.querySelector('td') // 4. Форма с name="search" // предполагаем, что есть только один элемент с таким name в документе let form = document.getElementsByName('search')[0] // или, именно форма: document.querySelector('form[name="search"]') // 5. Первый input в этой форме form.getElementsByTagName('input')[0] // или form.querySelector('input') // 6. Последний input в этой форме let inputs = form.querySelectorAll('input') // найти все input inputs[inputs.length-1] // взять последний

DOM — Поиск элементов

В этой главе рассказывается, как найти и получить доступ к HTML элементам на HTML странице.

Поиск HTML элементов

Часто в JavaScript необходимо проводить определенные манипуляции с HTML элементами.

Чтобы это сделать, сначала нужно найти требуемый элемент. Найти HTML элемент можно несколькими способами:

  • по идентификатору id
  • по имени тега
  • по имени класса
  • по селекторам CSS
  • по наборам объектов HTML

Поиск HTML элемента по идентификатору

Самый простой способ найти HTML элемент в DOM — это использовать его идентификатор id.

В следующем примере мы ищем элемент с id=»intro»:

 var myElement = document.getElementById("intro"); 

Если элемент будет найден, то он будет возвращен в виде объекта (в переменную myElement).

Если элемент не будет найден, то в переменная myElement будет содержать значение null.

Поиск HTML элемента по имени тега

В следующем примере мы ищем все элементы

:

 var x = document.getElementsByTagName("p"); 

В следующем примере сначала происходит поиск элемента с id=»main», а затем всех элементов

внутри «main»:

 var x = document.getElementById("main"); var y = x.getElementsByTagName("p"); 

Поиск HTML элемента по имени класса

Если нужно найти все HTML элементы с одним и тем же именем класса, то используют метод getElementsByClassName().

В следующем примере возвращается список всех элементов с атрибутом class=»intro»:

 var x = document.getElementsByClassName("intro"); 

Внимание! Поиск элементов по имени класса не работает в Internet Explorer 8 и более ранних версиях.

Поиск HTML элемента по CSS селекторам

Если нужно найти все HTML элементы, подходящие по заданному CSS селектору (id, имена классов, типы, атрибуты, значения атрибутов и т.п.), используется метод querySelectorAll().

В следующем примере возвращается список всех элементов

с атрибутом :

 var x = document.querySelectorAll("p.intro"); 

Внимание! Метод querySelectorAll() не работает в Internet Explorer 8 и более ранних версиях.

Поиск HTML элемента по наборам HTML объектов

В следующем примере производится поиск элемента формы с атрибутом в наборе объектов forms, и отображаются все значения элементов:

 var x = document.forms["frm1"]; var text = ""; var i; for (i = 0; i < x.length; i++) < text += x.elements[i].value + "
"; > document.getElementById("demo").innerHTML = text;

Также доступны следующие HTML объекты (и наборы объектов):

  • document.anchors
  • document.body
  • document.documentElement
  • document.embeds
  • document.forms
  • document.head
  • document.images
  • document.links
  • document.scripts
  • document.title

Как искать элементы в dom дереве

На чём стоят три слона, на которых держится веб?

Время чтения: меньше 5 мин

Открыть/закрыть навигацию по статье
Контрибьюторы:

Обновлено 6 октября 2022

Кратко

Скопировать ссылку «Кратко» Скопировано

DOM (Document Object Model) — это специальная древовидная структура, которая позволяет управлять HTML-разметкой из JavaScript-кода. Управление обычно состоит из добавления и удаления элементов, изменения их стилей и содержимого.

Браузер создаёт DOM при загрузке страницы, складывает его в переменную document и сообщает, что DOM создан, с помощью события DOM Content Loaded . С переменной document начинается любая работа с HTML-разметкой в JavaScript.

Как пишется

Скопировать ссылку «Как пишется» Скопировано

Объект document содержит большое количество свойств и методов, которые позволяют работать с HTML. Чаще всего используются методы, позволяющие найти элементы страницы.

Свойства

Скопировать ссылку «Свойства» Скопировано

  • title — заголовок документа. Браузер обычно показывает его на вкладке.

Установить свой заголовок можно простым присваиванием:

 document.title = 'Мое название документа'console.log(document.title)// Мое название документа document.title = 'Мое название документа' console.log(document.title) // Мое название документа      
  • forms — получить список форм на странице. Свойство только для чтения, напрямую перезаписать его нельзя.
  • body — получить элемент страницы.
  • head — получить элемент страницы.

Методы

Скопировать ссылку «Методы» Скопировано

  • get Element By Id — поиск элемента по идентификатору;
  • get Elements By Class Name — поиск элементов по названию класса;
  • get Elements By Tag Name — поиск элементов по названию тега;
  • query Selector — поиск первого элемента, подходящего под CSS-селектор;
  • query Selector All — поиск всех элементов подходящих под CSS-селектор.

Как понять

Скопировать ссылку «Как понять» Скопировано

Браузер создаёт DOM на основе HTML-кода страницы. Затем на основе DOM и других структур, браузер рисует страницу пользователю. При изменении DOM, браузер анализирует это и обновляет страницу.

DOM и страница, которую видит пользователь, связаны. Если изменишь одно, то изменится и второе:

  • пользователь заполняет форму — можно прочитать введённые значения в DOM;
  • при выборе страны, мы заполняем список городов в DOM — пользователь видит список.

Высокоуровневая схема такого взаимодействия:

Высокоуровневая схема взаимодействия DOM / HTML / JS / Страница браузера

Из чего состоит DOM

Скопировать ссылку «Из чего состоит DOM» Скопировано

HTML страница — это теги, вложенные друг в друга. Например:

Браузер превращает эту разметку в JavaScript представление, сохраняя при этом вложенность и свойства каждого HTML-элемента. Этого удаётся достичь с помощью специальной структуры данных — дерева.

Каждый тег представляет собой узел дерева. У каждого узла могут быть дочерние узлы — таким образом сохраняется информация о вложенности тегов. Правда, слово тег в этом контексте не используют и говорят элемент. Например, HTML-код выше превратится в такое дерево:

HTML-дерево

Дерево состоит из обычных и текстовых узлов. Обычные узлы — это HTML-теги, а текстовые узлы — текст внутри тегов.

Обычный узел называется Element , и он содержит в себе описание тега, атрибутов тега и обработчиков. Если изменить описание — изменится и HTML-код этого элемента (возможно что-то даже изменится на экране. Например, если поменять цвет шрифта). В статье Element мы разбираем всё необходимое для работы с элементами.

У любого узла есть один родительский узел и дочерние. Родительский узел — элемент, в который вложен текущий узел, он может быть только один. Дочерние — узлы, которые вложены в текущий узел.

Это правило не работает только в двух случаях:

  • корневой узел — у такого узла нет родителя;
  • текстовый узел — у таких узлов нет дочерних узлов, только родитель. Последний уровень любого DOM-дерева состоит из текстовых узлов.

На практике

Скопировать ссылку «На практике» Скопировано

Николай Лопин советует

Скопировать ссылку «Николай Лопин советует» Скопировано

�� Напрямую с DOM работают редко. Обычно работают на уровне элементов.

�� Из-за своей древовидной структуры искать элементы по DOM можно не только от корня. В диаграмме выше можно найти сначала элемент ul , а затем искать элементы среди его потомков.

 let ulElement = document.getElementsByTagName('ul')[0]// среди потомков ul нашли последний lilet lastLi = ulElement.querySelector('li:last-child') lastLi.style.color = 'red' let ulElement = document.getElementsByTagName('ul')[0] // среди потомков ul нашли последний li let lastLi = ulElement.querySelector('li:last-child') lastLi.style.color = 'red'      

Методы поиска элементов в DOM

На этом занятии рассмотрим методы поиска произвольных элементов в HTML-документе. Рассмотренные свойства на предыдущем занятии по навигации DOM-дереву хороши если элементы расположены рядом. Но что делать, если требуемый объект может находиться в самых разных местах. Как его искать? Вот об этом и пойдет сейчас речь.

В самом простом случае мы можем у любого тега HTML-документа прописать атрибут id с некоторым уникальным значением. Например:

DOCTYPE html> html> head> title>Уроки по JavaScripttitle> head> body> div id="div_id"> p>Текст внутри блока div div> script> script> body> html>

Здесь у нас тег div имеет атрибут id со значением div_id. Мы это значение придумываем сами, главное, чтобы оно было уникальным в пределах HTML-страницы. Теперь можно получить этот элемент div по этому id, где бы он ни находился в DOM-дереве. Для этого используется метод getElementById объекта document:

let divElem = document.getElementById('div_id'); console.log( divElem );

Мы в методе getElementById в качестве аргумента указываем строку со значением атрибута id и на выходе получаем ссылку на этот элемент.

Или же можем получить доступ к этому элементу напрямую через глобальную переменную div_id, которая автоматически создается браузером при формировании DOM-дерева:

console.log( div_id );

Но этот второй способ имеет одну уязвимость: если мы создадим в скрипте переменную с таким же именем, то прежнее значение div_id будет затерто:

let div_id = "не тег div";

так что этот подход следует применять с большой осторожностью, лучше использовать метод getElementById.

В стандарте ES6+ появился новый метод поиска элементов querySelectorAll, который возвращает список элементов, удовлетворяющих CSS-селектору, который мы в нем указываем.

Например, добавим в HTML-документ вот такой маркированный список:

ul> li>Солнце li>Меркурий li>Венера li>Земля li>Марс ul>

и вот такой нумерованный список:

p>Звезды: ol> li>Сириус li>Альдебаран li>Капелла li>Ригель ol>
let list = document.querySelectorAll("ul > li"); for(let val of list) console.log(val);

Как видите, у нас были выбраны элементы только маркированного списка. Мало того, в методе querySelectorAll можно использовать псевдоклассы для указания более сложных CSS-селекторов, например, так:

let list = document.querySelectorAll("ul > li:first-child");

тогда мы увидим только первый элемент списка. И так далее. С помощью querySelectorAll можно довольно просто выбрать нужные элементы и далее производить с ними необходимые действия.

Если же нам нужно по определенному CSS-селектору найти только первый подходящий элемент, то для этого применяется другой метод querySelector:

let element = document.querySelector("ol > li"); console.log(element);
let element = document.querySelectorAll("ol > li")[0];

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

Следующий метод matches позволяет определить: подходит ли данный элемент под указанный CSS-селектор или нет. Если подходит, то возвращает true, иначе – false. Например, создадим такое оглавление:

h1>О звездахh1> div class="content-table"> ul class="stars-list"> li class="star">О сириусеli> li class="star">Об альдебаранеli> li class="contact">Обратная связьli> ul> div>

И мы, перебирая список пунктов меню, хотим выбрать только те элементы, у которых class равен star. Это можно сделать так:

let list = document.querySelectorAll("ul.stars-list > li"); for(let item of list) { if(item.matches("li.star")) console.log(item); }

Обратите внимание, что метод matches относится к объекту DOM, а не к document. Что, в общем-то логично, так как нам нужно проверить конкретный элемент на соответствие CSS-селектора. В результате, в консоле мы увидим первые два элемента:

li class="star">О сириусеli> li class="star">Об альдебаранеli>

Следующий метод elem.closest(css) ищет ближайшего предка, который соответствует CSS-селектору. Сам элемент также включается в поиск. Метод возвращает либо предка, либо null, если такой элемент не найден. Например:

let li = document.querySelector("li.star"); console.log(li.closest('.stars-list')); console.log(li.closest('.content-table')); console.log(li.closest('h1')); // null

Сначала мы выбираем первый элемент li пункта меню. Затем, с помощью метода closest ищем ближайшего родителя с классом stars-list. Находится список ul. Далее, ищем родителя с классом content-table. Находим блок div. Наконец, пытаемся найти родителя с тегом h1. Но его нет, так как h1 в документе не является родителем для объекта li. Получаем значение null.

  • elem.getElementsByTagName(tag) ищет элементы с указанным тегом и возвращает их коллекцию. Указав «*» вместо тега, можно получить всех потомков.
  • elem.getElementsByClassName(className) возвращает элементы, которые имеют указанный CSS-класс.
  • document.getElementsByName(name) возвращает элементы с заданным атрибутом name. (Используется очень редко).
DOCTYPE html> html> head> title>Уроки по JavaScripttitle> head> body> h1>О звездахh1> h2>Об альдебаранеh2> script> let list = document.getElementsByTagName("h2"); script> h2>О ригелеh2> script> for(let item of list) console.log(item); script> body> html>

Мы в консоле увидим список из двух тегов h2, хотя когда этот список формировался в HTML-документе был всего один тег h2. Второй добавился позже, автоматически. Но, если мы будем получать список этих элементов с помощью метода querySelectorAll:

let list = document.querySelectorAll("h2");

то увидим только один тег h2. Так как здесь делается как бы снимок коллекции на текущий момент состояния HTML-документа и после этого никак не меняется. Вот этот момент при работе с этими методами следует иметь в виду. Ну и в заключение этого занятия отметим еще один полезный метод

elemA.contains(elemB)

который возвращает значение true, если elemB является дочерним по отношению к elemA. И false в противном случае. Например, вот в этом документе:

div class="content-table"> ul class="stars-list"> li class="star">О сириусеli> li class="star">Об альдебаранеli> li class="contact">Обратная связьli> ul> div>

Можно проверить: имеется ли список внутри тега div:

let div = document.querySelector("div.content-table"); let ul = document.querySelector("ul.stars-list"); if(div.contains(ul)) console.log("ul внутри div");

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *