Далее на странице...
Как путешествовать по DOM-дереву при помощи JavaScript. Как получить доступ к родительским и дочерним элементам?
Как работают: свойство parentNode, метод childNodes, свойства firstChild и lastChild; nextSibling и previousSibling.
На практике часто нужно получить доступ к определенному элементу страницы и затем обратиться к его родителю или к следующему элементу: и взаимодействовать уже с ними - например, поменять стилевое оформление/класс.
Для работы будет использоваться тестовая html-страница.
HTML-код
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="wrapper">
<div class="first">
<button></button>
<button id="current"></button>
<button></button>
</div>
<div class="second">
<ul>
<li>1</li>
<li>2</li>
<li data-current="3">3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
<div class="third"></div>
</div>
<!-- renernh -->
<script src="script.js"></script>
</body>
</html>
Результат в Браузере
Доступ к DOM - Объект document
Доступ к DOM начинается с объекта document - через него можно добраться до любых узлов/элементов страницы.
document.head - доступ к тегу head.
document.body - доступ к тегу body.
Свойство documentElement объекта document позволяет получить доступ к коренному элементу документа/к вершине DOM-дерева. Для html-страницы - это будет тег <html>.
Пример №1
JavaScript-код
'use strict';
console.log(document.head);
console.log(document.body);
console.log(document.documentElement);
Результат в Браузере
Родительские и дочерние элементы
Родительский элемент - это тот, который объединяет другие, находящиеся внутри него.
Теги head и body являются дочерними по отношению к тегу html, который соответственно является родителем.
Внутри тегов head и body также есть дочерние элементы: при этом head и body являются уже родительскими по отношению к ним.
Как родительские, так и дочерние элементы мы можем получать при помощи различных команд/методов.
Метод childNodes
Метод childNodes возвращает псевдомассив из дочерних элементов.
Для примера при помощи метода childNodes получим доступ узлам/элементам, которые являются дочерними по отношению к тегу body.
Пример №2
JavaScript-код
'use strict';
console.log(document.body.childNodes);
Результат в Браузере
Результат в консоли
NodeList(6) [text, div.wrapper, text, comment, text, script]
0: text
1: div.wrapper
2: text
3: comment
4: text
5: script
6: text
length: 7
[[Prototype]]: NodeList
В результате мы получаем псевдомассив NodeList, состоящий из 7-ми элементов. Что это за элементы?
- во-первых, это текстовые узлы (всего их 4 и на сленге это body и тегом div с классом wrapper.
или одна от англ. Node дословно переводится как узел). Например, первый текстовый узел - это перенос строки между тегомИтак, перенос строки в JavaScript - это текстовый узел, который мы явно не видим.
- следующий узел - это тег div с классом wrapper.
- далее идет комментарий comment и тег script - подключение к файлу со скриптами script.js.
DOM-элементы и DOM-узлы
Здесь следует заострить внимание на разнице между DOM-элементами и DOM-узлами.
Можно сказать так: каждая "сущность", которая находится в коде (на веб-странице) является узлом. Но не каждый узел является элементом.
Например, теги что мы видим в html-коде - это DOM-элементы, а перенос строки между ними - это DOM-узел (текстовый узел).
Еще пример: тег li - это DOM-элемент, внутри которого есть текстовый DOM-узел - это цифра 1.
Свойства firstChild и lastChild
Свойства firstChild и lastChild возвращают первый и последний дочерний элемент.
Пример №3
JavaScript-код
'use strict';
console.log(document.body.firstChild);
console.log(document.body.lastChild);
Результат в Браузере
Результат в консоли
#text
<script src="script.js"></script>
В консоли мы увидим первый дочерний элемент (firstChild) тега body - это текстовый узел (перенос строки) и последний дочерний элемент (lastChild) тела документа - это script, где происходит подключение файла со скриптами к веб-странице.
Доступ к родительскому элементу - Свойство parentNode
Свойство parentNode возвращает родительский элемент.
Пример №4.1
JavaScript-код
'use strict';
console.log(document.querySelector('#current').parentNode);
Результат в Браузере
Сначала при помощи метода querySelector получаем доступ к произвольному элементу страницы с id = "current" (при этом результат не заносится в переменную - это не обязательно) и затем, используя свойство parentNode, получаем доступ к родительскому элементу - это тег div с классом first.
Используя свойство parentNode дважды, можно подняться на уровень выше и получить доступ к "родителю - родителя". В нашем случае - к родителю тега div с классом first, то есть к тегу div с классом wrapper.
Пример №4.2
JavaScript-код
'use strict';
console.log(document.querySelector('#current').parentNode.parentNode);
Результат в Браузере
data-атрибуты - Синтаксис
Поговорим еще об одной возможности, которая появилась в HTML-5 - это data-атрибуты.
Дело в следующем: работая с DOM-деревом и прописывая различные скрипты, не всегда хватает ориентиров и не всегда назначение id для элементов страницы является удобным. Так появились data-атрибуты с помощью которых можно делать удобные метки, а также получать доступ к элементам страницы.
Синтаксис при использовании data-атрибутов прост.
Любой атрибут, чьё имя начинается с data-, является data-атрибутом.
data-name = "value" или data-name
name - произвольное название data-атрибута - как правило это строка;
value - значение data-атрибута (не обязательный параметр) - это как правило число или строка;
Если data-атрибут используется без значения value, то он принимает логическое значение .
В html-коде исходной страницы видно, что для одного из элементов списка - для 3-го тега <li> назначен data-атрибут data-current со значением 3.
Далее используем data-атрибут для получения доступа к соответствующим узлам.
Свойства nextSibling и previousSibling
Свойства nextSibling и previousSibling позволяют получить доступ к следующему и предыдущему узлу соответственно.
Пример №5
JavaScript-код
'use strict';
console.log(document.querySelector('[data-current="3"]').nextSibling);
console.log(document.querySelector('[data-current="3"]').previousSibling);
Результат в Браузере
Результат в консоли
#text
#text
-
При помощи метода querySelector и data-атрибута data-current="3" получаем доступ к соответствующему тегу li.
При подобной работе с data-атрибутами их название вместе со значением помещается в квадратные скобки: querySelector('[data-current="3"]')
-
Затем при помощи свойств nextSibling и previousSibling получаем доступ к следующему и предыдущему узлу - это текстовые узлы (переносы строк).
Как быть в этом и подобных случаях? Об этом далее.
Доступ к узлам и доступ к элементам
Итак, только что мы разобрали как работают методы/свойства parentNode, childNodes, firstChild и lastChild; nextSibling и previousSibling.
Все эти методы ориентированы на "ноды" (от англ. Node дословно переводится как узел), то есть благодаря этим методам мы получаем доступ именно к узлам DOM-дерева (слово Node даже присутствует в названиях некоторых из них).
При этом, мы легко можем попасть на ненужный нам узел (не содержащий в себе какой-либо элемент страницы) - например перенос строки (см. пример №2).
Так вот у этих методов есть аналоги, которые будут рассмотрены на следующей странице, и благодаря которым есть возможность получать именно элементы страницы.