Типы и содержимое узлов DOM

Информация об узлах DOM

Узлы DOM-дерева могут сильно отличаться друг от друга. Узлы разных типов имеют различные свойства. Следовательно, прежде, чем начать работу с конкретным узлом, может потребоваться получить информацию о нём. В DOM-интерфейсе имеется несколько общих свойств для всех узлов, которые представляют информацию о текущем узле.

nodeType

Узлы DOM-дерева бывают разных типов. Всего существует 12 типов узлов, но на практике работать необходимо только с несколькими:

  • элементы;
  • текстовые узлы;
  • комментарии.

Свойство nodeType содержит код, соответствующий типу узла. В частности:

  • 1 - для элементов;
  • 3 - для текстовых узлов;
  • 8 - для комментариев.

Запоминать эти коды необязательно. Чтобы узнать тип узла, можно выполнить проверку принадлежности к соответствующему классу с помощью оператора instanceof:

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <p>Параграф</p>
</body>
</html>
 
<script>
var par = document.body.firstElementChild;
var node = document.body.firstChild;
alert(par.nodeType == '1'); /* true */
alert(par instanceof Element); /* true */
alert(node.nodeType == '3'); /* true */
alert(node instanceof Text); /* true */
</script>

nodeName

Более подробную информацию об узле можно получить из свойства nodeName. В нём содержится имя узла. Для тегов - это имя тега в верхнем регистре, для текстовых узлов и комментариев - тип узла:

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <p>Параграф</p>
</body>
</html>
 
<script>
var par = document.body.firstElementChild;
var node = document.body.firstChild;
alert(par.nodeName); /* 'P' */
alert(node.nodeName); /* '#text' */
</script>

tagName

Для узлов элементов введено свойство tagName, которое, как и свойство nodeName, содержит имя тега в верхнем регистре. Для текстовых узлов и комментариев данное свойство выдаёт undefined.

Содержимое узлов DOM

При работе с DOM-узлами часто бывает необходимо получить информацию, содержащуюся в них, или даже заменить её. В DOM-интерфейсе предусмотрено несколько свойств для работы с содержимым узлов.

innerHTML

Свойство innerHTML доступно только для узлов элементов и является самым распространённым. Оно в строковом формате содержит весь код, находящийся внутри данного элемента. Данное свойство доступно для перезаписи, поэтому с его помощью можно не только получить необходимую информацию, но и поменять содержимое элемента.

По определению очевидно, что данное свойство доступно только для парных тегов.

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <p>Lorem ipsum dolor...</p>
</body>
</html>

<script>
  var par = document.querySelector('p');
  var par_content = par.innerHTML;
  alert(par_content); /* 'Lorem ipsum dolor...' */
  par.innerHTML = '<a href="" title="На главную">' + par_content + '</a>'; /* текст стал ссылкой */
</script>

Свойство innerHTML имеет ряд особенностей, которые необходимо знать.

В innerHTML можно записать любой текст, но при чтении всегда возвращается валидный HTML-код.

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
</body>
</html>

<script>
  document.body.innerHTML = '<p>Lorem ipsum dolor...';
  alert(document.body.innerHTML); /* '<p>Lorem ipsum dolor...</p>' */
</script>

При любом изменении innerHTML элемент полностью отображается заново. То есть, если innerHTML содержит несколько элементов и к ним добавить ещё один, то всё равно элементы будут созданы заново. Это может сильно замедлить отображение страницы. Для добавления или удаления элементов лучше использовать специальные методы.

outerHTML

Свойство outerHTML доступно для всех узлов элементов. Оно представляет строку, в которой указано всё содержимое узла, включая открывающий и закрывающий теги.

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <ul>
    <li>Lorem ipsum dolor...</li>
  </ul>
</body>
</html>

<script>
  var list_item = document.querySelector('li');
  alert(list_item.outerHTML); /* '<li>Lorem ipsum dolor...</li>' */
</script>

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

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

Для работы с новым элементом сначала придётся его найти. Если в этом нет необходимости, то использование outerHTML может быть очень удобным.

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <p><span>Lorem ipsum dolor...</span></p>
</body>
</html>

<script>
  var span = document.querySelector('span');
  alert(span.outerHTML); /* '<span>Lorem ipsum dolor...</span>' */
  span.outerHTML = '<b>Lorem...</b>'; /* элемент на странице изменился */
  alert(span.outerHTML); /* '<span>Lorem ipsum dolor...</span>' */
</script>

Вышеприведённый пример показывает, что замена элемента происходит, как и положено. Однако, свойство outerHTML остаётся неизменным.

Свойство outerHTML используется редко. Для получения только содержимого элемента проще воспользоваться свойством innerHTML. Наиболее очевидным случаем для использования outerHTML является определение тега элемента. Но и в этом случае проще воспользоваться отдельным свойством tagName.

textContent

Свойство textContent содержит только текст, расположенный внутри элемента. Теги не включаются в возвращаемую строку.

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <ul>
    <li>Lorem</li>
    <li>ipsum</li>
    <li>dolor</li>
  </ul>
</body>
</html>

<script>
  var list = document.querySelector('ul');
  alert(list.textContent);
/*
    Lorem
    ipsum
    dolor
*/
</script>

Переносы строки тоже включаются в значение свойства. Получается, что textContent является суммированием всех текстовых узлов элемента.

Свойство textContent доступно для записи. Это бывает очень полезно, так как всё, что попадает в это свойство, автоматически становится строкой. Например, попытка внедрить вредоносный код окажется безуспешной, так как он не выполнится.

data

Предыдущие свойства позволяют получить содержимое только узлов элементов. Свойство data используется для получения значений текстовых узлов и комментариев. Для узлов элементов оно не доступно.

<html>
<head>
  <title>DOM интерфейс</title>
</head>
<body>
  <p><!-- Lorem --> ipsum <span>dolor</span></p>
</body>
</html>

<script>
  var par = document.querySelector('p');
  alert(par.childNodes[0].data); /* ' Lorem ' */
  alert(par.childNodes[1].data); /* ' ipsum ' */
  alert(par.childNodes[2].data); /* undefined, свойство data отсутствует */
</script>