- JavaScript | Как получить всех детей?
- Видео инструкция
- Навигация по DOM-элементам
- Сверху: documentElement и body
- Дети: childNodes, firstChild, lastChild
- DOM-коллекции
- Соседи и родитель
- Навигация только по элементам
- JavaScript | Как получить всех потомков DOM-элемента?
- Информационные ссылки
- Вам также может понравиться
- JavaScript | Как найти одинаковые числа в двух массивах?
- Referrer Policy (Русская версия)
- document.getElementsByTagName(«caption»)
- ECMAScript | Оператор switch
JavaScript | Как получить всех детей?
Объектная модель документа преобразовывает все HTML-элементы в объекты JavaScript. У элементов на странице есть своя структура вложенности одного в другого. Из этого можно сделать вывод, что каждый элемент «родственно» может быть связан с другим. Какой-то элемент может быть родителем, а какой-то его ребёнком.
Как получить всех детей элемента на странице?
Для примера возьмём разметку:
"odin">телефон
телевизор
телескоп
"dva">Иван
Николай
Максим
"tri">купить
продать
обменять
Видео инструкция
В этом видео приводится пример получения детей элемента при помощи JavaScript. Ввод команд осуществляется в консоль браузера Google Chrome. Результат виден сразу.
Для начала поучим все элементы :
document.getElementsByTagName("div")
Обратите внимание как мы это сделали. Мы обратились ко всему документу и из него вытащили все элементы div. При таком способе мы не можем сказать, что все элементы данной HTML-коллекции являются детьми объекта document. Чьими же детьми они являются? Как всё-таки получить именно детей?
Для решения задачи мы будем получать значение атрибута «children«, который будем вызывать на элементе/узле. Вся разметка у нас лежит внутри элемента body, поэтому мы будем получать его детей.
Визуально коллекция не поменялась, но концептуально мы получили детей элемента, которые лежат на одном уровне вложенности. Это снова три элемента div со своими структурами, но в другом отношении. Теперь с уверенностью можно сказать, что это дети одного родителя.
А теперь давайте подумаем как мы можем обратиться к параграфам с мужскими именами? Если мы соберём все параграфы при помощи document.getElementsByTagName(«p»), то это будет просто бессвязный набор:
document.getElementsByTagName("p")
Но если мы получим всех детей второго div, то это будет то что надо:
document.body.children[1].children
В этом примере мы получили детей из детей.
Навигация по DOM-элементам
DOM позволяет нам делать что угодно с элементами и их содержимым, но для начала нужно получить соответствующий DOM-объект.
Все операции с DOM начинаются с объекта document . Это главная «точка входа» в DOM. Из него мы можем получить доступ к любому узлу.
Так выглядят основные ссылки, по которым можно переходить между узлами DOM:
Поговорим об этом подробнее.
Сверху: documentElement и body
Самые верхние элементы дерева доступны как свойства объекта document :
= document.documentElement Самый верхний узел документа: document.documentElement . В DOM он соответствует тегу . = document.body Другой часто используемый DOM-узел – узел тега : document.body . = document.head Тег доступен как document.head .
Нельзя получить доступ к элементу, которого ещё не существует в момент выполнения скрипта.
В частности, если скрипт находится в , document.body в нём недоступен, потому что браузер его ещё не прочитал.
Поэтому, в примере ниже первый alert выведет null :
В DOM значение null значит «не существует» или «нет такого узла».
Дети: childNodes, firstChild, lastChild
Здесь и далее мы будем использовать два принципиально разных термина:
- Дочерние узлы (или дети) – элементы, которые являются непосредственными детьми узла. Другими словами, элементы, которые лежат непосредственно внутри данного. Например, и являются детьми элемента .
- Потомки – все элементы, которые лежат внутри данного, включая детей, их детей и т.д.
- (и несколько пустых текстовых узлов):
- и вложенные в них:
(ребёнок
- ) и (ребёнок
) – в общем, все элементы поддерева.
Коллекция childNodes содержит список всех детей, включая текстовые узлы.
Пример ниже последовательно выведет детей document.body :
Обратим внимание на маленькую деталь. Если запустить пример выше, то последним будет выведен элемент . На самом деле, в документе есть ещё «какой-то HTML-код», но на момент выполнения скрипта браузер ещё до него не дошёл, поэтому скрипт не видит его.
Свойства firstChild и lastChild обеспечивают быстрый доступ к первому и последнему дочернему элементу.
Они, по сути, являются всего лишь сокращениями. Если у тега есть дочерние узлы, условие ниже всегда верно:
elem.childNodes[0] === elem.firstChild elem.childNodes[elem.childNodes.length - 1] === elem.lastChild
Для проверки наличия дочерних узлов существует также специальная функция elem.hasChildNodes() .
DOM-коллекции
Как мы уже видели, childNodes похож на массив. На самом деле это не массив, а коллекция – особый перебираемый объект-псевдомассив.
И есть два важных следствия из этого:
for (let node of document.body.childNodes) < alert(node); // покажет все узлы из коллекции >
Это работает, потому что коллекция является перебираемым объектом (есть требуемый для этого метод Symbol.iterator ).
alert(document.body.childNodes.filter); // undefined (у коллекции нет метода filter!)
Первый пункт – это хорошо для нас. Второй – бывает неудобен, но можно пережить. Если нам хочется использовать именно методы массива, то мы можем создать настоящий массив из коллекции, используя Array.from :
alert( Array.from(document.body.childNodes).filter ); // сделали массив
DOM-коллекции, и даже более – все навигационные свойства, перечисленные в этой главе, доступны только для чтения.
Мы не можем заменить один дочерний узел на другой, просто написав childNodes[i] = . .
Для изменения DOM требуются другие методы. Мы увидим их в следующей главе.
Почти все DOM-коллекции, за небольшим исключением, живые. Другими словами, они отражают текущее состояние DOM.
Если мы сохраним ссылку на elem.childNodes и добавим/удалим узлы в DOM, то они появятся в сохранённой коллекции автоматически.
Коллекции перебираются циклом for..of . Некоторые начинающие разработчики пытаются использовать для этого цикл for..in .
Не делайте так. Цикл for..in перебирает все перечисляемые свойства. А у коллекций есть некоторые «лишние», редко используемые свойства, которые обычно нам не нужны:
Соседи и родитель
Соседи – это узлы, у которых один и тот же родитель.
- говорят, что – «следующий» или «правый» сосед
- также можно сказать, что «предыдущий» или «левый» сосед .
Следующий узел того же родителя (следующий сосед) – в свойстве nextSibling , а предыдущий – в previousSibling .
Родитель доступен через parentNode .
// родителем является alert( document.body.parentNode === document.documentElement ); // выведет true // после идёт alert( document.head.nextSibling ); // HTMLBodyElement // перед находится alert( document.body.previousSibling ); // HTMLHeadElement
Навигация только по элементам
Навигационные свойства, описанные выше, относятся ко всем узлам в документе. В частности, в childNodes находятся и текстовые узлы и узлы-элементы и узлы-комментарии, если они есть.
Но для большинства задач текстовые узлы и узлы-комментарии нам не нужны. Мы хотим манипулировать узлами-элементами, которые представляют собой теги и формируют структуру страницы.
Поэтому давайте рассмотрим дополнительный набор ссылок, которые учитывают только узлы-элементы:
Эти ссылки похожи на те, что раньше, только в ряде мест стоит слово Element :
- children – коллекция детей, которые являются элементами.
- firstElementChild , lastElementChild – первый и последний дочерний элемент.
- previousElementSibling , nextElementSibling – соседи-элементы.
- parentElement – родитель-элемент.
Свойство parentElement возвращает родитель-элемент, а parentNode возвращает «любого родителя». Обычно эти свойства одинаковы: они оба получают родителя.
За исключением document.documentElement :
alert( document.documentElement.parentNode ); // выведет document alert( document.documentElement.parentElement ); // выведет null
Причина в том, что родителем корневого узла document.documentElement ( ) является document . Но document – это не узел-элемент, так что parentNode вернёт его, а parentElement нет.
Эта деталь может быть полезна, если мы хотим пройти вверх по цепочке родителей от произвольного элемента elem к , но не до document :
while(elem = elem.parentElement) < // идти наверх до alert( elem ); >
Изменим один из примеров выше: заменим childNodes на children . Теперь цикл выводит только элементы:
JavaScript | Как получить всех потомков DOM-элемента?
У нас есть DOM-элемент, который имеет разную структуру вложенности одного в другой. Нам нужно получить всех его потомков — детей, детей у детей, детей у тех детей и так далее до конца. Как это сделать?
Для этого нужно сначала получить сам элемент element и уже у него вызвать метод getElementsByTagName() . В качестве параметра нужно передать строку, которая будет состоять из одного символа звёздочки *
element.getElementsByTagName("*")
Информационные ссылки
Перевод стандарта Объектной Модели Документа — DOM — https://efim360.ru/dom/
Стандарт DOM — Раздел «4.5. Interface Document» — Блок «Для разработчиков» — https://dom.spec.whatwg.org/#interface-document
Вам также может понравиться
JavaScript | Как найти одинаковые числа в двух массивах?
Как найти пересечение между двумя массивами JavaScript? У нас есть два массива с уникальными наборами чисел: let arr1 = [1,2,3,4,5,6]; let arr2 […]
Referrer Policy (Русская версия)
Редакция от 25 мая 2022 г. Резюме В этом документе описывается, как автор может установить политику рефёрера (referrer policy) для создаваемых […]
document.getElementsByTagName(«caption»)
Команда document.getElementsByTagName(«caption») возвращает HTML-коллекцию HTML-элементов со страницы (документа). Элементы коллекции тянут за собой всех потомков. Забор данных осуществляется в древовидном порядке, […]
ECMAScript | Оператор switch
Синтаксис оператора switch SwitchStatement [Yield, Await, Return] : switch ( Expression [+In, ?Yield, ?Await] ) CaseBlock [?Yield, ?Await, ?Return] CaseBlock [Yield, Await, […]