Получение элементов по дереву Node
Как мы уже знаем структурой DOM является дерево. Оно состоит из связанных друг с другом узлов. Узлы бывают разных типов, в зависимости от того, чему соответствует этот узел в HTML. То есть при преобразовании HTML-текста в DOM, разные сущности в нём преобразуются в разные типы узлов.
Основную структуру DOM-дерева составляют именно узлы, образованные HTML-тегами. Их называют узлами-элементами или просто элементами.
Узнать тип узла в DOM можно с помощью свойства nodeType
:
// 9
console.log(document.nodeType);
// 1
console.log(document.body.nodeType);
Это свойство возвращает число от 1 до 12, обозначающее тип узла:
1
– элементNode.ELEMENT_NODE
2
– атрибутNode.ATTRIBUTE_NODE
3
– текстовый узелNode.TEXT_NODE
8
– комментарийNode.COMMENT_NODE
9
– documentNode.DOCUMENT_NODE
10
– узел, содержащий тип документаNode.DOCUMENT_TYPE_NODE
11
– узел, представляющий фрагмент документаDocumentFragment
Node.DOCUMENT_FRAGMENT_NODE
В скобках приведены константы класса Node
. Они обычно используются в коде, когда нужно проверить тип DOM-узла в JavaScript. Их намного удобнее использовать, чем запоминать числовые коды:
// false
console.log(document.body.nodeType === Node.DOCUMENT_NODE);
// true
console.log(document.body.nodeType === Node.ELEMENT_NODE);
Например, получим doctype
документа и узнаем его числовой код:
const doctype = document.doctype;
// или так
const doctypeSame = document.childNodes[0];
// получим числовой код узла 10
console.log(doctype.nodeType);
// получим числовой код узла 10
console.log(doctypeSame.nodeType);
Теперь изучим свойство nodeName. С его помощью мы можем узнать имя узла или тег, если узел является элементом:
// "BODY"
console.log(document.body.nodeName);
// "html"
console.log(document.doctype.nodeName);
// #document"
console.log(document.nodeName);
Свойство nodeName
для других узлов, не являющимися элементами возвращает различные значения:
- для текстовых узлов
"#text"
- для узлов-комментариев
"#comment"
- для
document
"#document"
и так далее
Получить имя тега элемента можно не только с помощью nodeName
, но также посредством свойства tagName
. tagName
запрограммирован в браузере как геттер, он содержится в prototype
класса Element
. nodeName
– это тоже геттер, но находится он в другом месте, в prototype
класса Node
. Поэтому свойство tagName
доступно только для узлов-элементов, и не доступно для других типов узлов.
Полный список свойств, с помощью которых мы можем получить информацию о данном узле:
childNodes()
содержит коллекцию дочерних узлов, примерfirstChild()
возвращает первый дочерний узел текущего узла, примерlastChild()
возвращает последний дочерний узел текущего узла, примерpreviousSibling()
возвращает предыдущий элемент, который находится на одном уровне с текущимnextSibling()
возвращает следующий элемент, который находится на одном уровне с текущимownerDocument()
возвращает корневой узел документаparentNode()
возвращает элемент, который содержит текущий узел, примерnodeName()
возвращает имя узлаnodeType()
возвращает тип узла в виде числаnodeValue()
возвращает или устанавливает значение узла в виде простого текстаfirstElementChild()
находит первый элемент у родителя, примерlastElementChild()
находит последний элемент родителя, примерchildren()
находит псевдомасив элементов родителей, примерparentElement()
содержит родительский элемент, примерpreviousElementSibling()
содержит предыдущий элемент, находящийся в этом же родителе, примерnextElementSibling()
содержит следующий элемент, находящийся в этом же родителе, пример
Перебирем все дочерние узлы элемента:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div class="article">
<h3>Заголовок статьи</h3>
<p>Первый абзац</p>
<p>Второй абзац</p>
</div>
<script>
var articleDiv = document.querySelector("div.article");
var nodes = articleDiv.childNodes;
for(var i=0; i<nodes.length;i++){
var type = "";
if(nodes[i].nodeType===1)
type="элемент";
else if(nodes[i].nodeType===2)
type="атрибут";
else if(nodes[i].nodeType===3)
type="текст";
console.log(nodes[i].nodeName + ": " + type);
}
</script>
</body>
</html>
С помощью метода document.querySelector("div.article")
выбираем элемент div
с классом article
и пробегаемся по его дочерним узлам. И в цикле выводим имя узла и его тип с помощью свойств nodeName и nodeType
.
Навигация по узлам
Используя свойства nextSibling
и previousSibling
можно также пройтись по узлам в прямом или обратном порядке. Например, для прохода по элементам на той же станице мы могли бы использовать следующий код javascript:
var articleDiv = document.querySelector("div.article");
// получаем первый дочерний элемент
var node = articleDiv.firstChild;
console.log(node.nodeName);
// обращаемся к следующему узлу, пока он определен
while((node=node.nextSibling)!==null){
console.log(node.nodeName);
}
Тут все аналогично, только в цикле мы обращаемся к следующему узлу, который находится на одном уровне с текущим (или сестринскому узлу). И результат будет такой же.
Также можно перебрать узлы в обратном порядке: сначала получаем последний узел, а затем обращаемся к предыдущему сестринскому узлу:
var articleDiv = document.querySelector("div.article");
// получаем последний дочерний элемент
var node = articleDiv.lastChild;
console.log(node.nodeName);
// обращаемся к предыдующему узлу, пока он определен
while((node=node.previousSibling)!==null){
console.log(node.nodeName);
}