Атрибуты и свойства элементов в DOM
При построении страницы браузер берёт информацию об элементах из их атрибутов. Но, кроме того, все элементы страницы являются объектами со своими свойствами, которые также учитываются при отображении элементов. DOM-интерфейс позволяет работать и с атрибутами элементов и с их свойствами. При этом необходимо понимать разницу между ними, знать, что и где использовать.
Атрибуты элементов
В HTML-документах теги могут иметь определённые атрибуты с заданными значениями. Атрибуты могут влиять на отображение элемента на странице или изменять его назначение. Поэтому для манипулирования элементами страницы должна быть предоставлена возможность работы с атрибутами HTML-тегов.
DOM-интерфейс представляет набор методов для работы с атрибутами элементов.
element.hasAttribute(атрибут)
- Проверяет наличие атрибута.
element.getAttribute(атрибут)
- Возвращает строку со значением атрибута.
element.setAttribute(атрибут, значение)
- Создаёт атрибут или присваивает ему новое значение.
element.removeAttribute(атрибут)
- Удаляет атрибут.
Эти методы работают именно с HTML-атрибутами как они есть в документе. Фактически, они изменяют код страницы. Поэтому для них справедливо:
- Значения атрибутов - это всегда строки.
- Имя атрибута можно указывать в любом регистре, так как HTML не предъявляет требований к регистру символов в коде.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><a>Первый</a></p> </body> </html> <script> var anch = document.querySelector('a'); alert(anch.hasAttribute('href')); /* false */ anch.setAttribute('href', 'home.html'); alert(anch.getAttribute('href')); /* строка 'home.html' */ anch.removeAttribute('HREF'); alert(anch.hasAttribute('href')); /* false, атрибут удалился вне зависимости от регистра */ </script>
Свойства элементов
В DOM каждый элемент является объектом своего класса. При создании модели страницы для каждого элемента браузер создаёт определённые свойства. В них содержится информация о текущем состоянии данного элемента, которую можно изменить. Также, любому элементу можно присвоить совершенно любые свойства, как и для любого объекта в JavaScript.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p>Lorem ipsum dolor...</p> </body> </html> <script> var par = document.querySelector('p'); par.firstParagraph = true; alert(par.firstParagraph); /* true */ </script>
В отличие от атрибутов:
- Значение свойства может быть любого типа.
- Имена свойств регистрозависимы.
Связь свойств с атрибутами
В DOM-интерфейсе понятия HTML-атрибутов и DOM-свойств элементов тесно связаны. При создании модели страницы для каждого элемента создаются одноимённые с атрибутами свойства и присваиваются им те же значения. Однако, это справедливо не для всех атрибутов, что приводит к некоторой путанице, но, чаще, это бывает полезно.
При выводе в окне браузера параметры элемента зависят именно от его свойств. Дальнейшее управление элементами на странице осуществляется изменением этих свойств. Поэтому в основном требуется работать со свойствами элементов, а не с артибутами. Атрибуты, обычно, используются для хранения информации.
Например, поле для ввода текста <input>
имеет атрибут value
. При построении документа создаётся элемент со свойством value
, которое имеет значение, указанное в HTML-коде страницы. Текст для отображения в поле берётся именно из свойства value
. Если пользователь вводит свой текст в поле, то свойство автоматически принимает новое текущее значение. При этом код страницы не меняется, поэтому первоначальное значение атрибута остаётся доступным.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><input type="text" value="Текст" autocomplete="off"></p> </body> </html> <script> var input = document.querySelector('input'); alert('Свойство: ' + input.value); /* 'Свойство: Текст' */ input.value = 'Новый текст'; /* изменили текст в поле */ alert('Свойство: ' + input.value + '\nАтрибут: ' + input.getAttribute('value')); /* Атрибут не изменился */ </script>
В примере видно, что изменение свойства value
не отражается на значении атрибута value
. Таким образом, сравнив значения атрибута и свойства, можно понять, был ли изменён текст в поле.
Для элементов создаются свойства не только из указанных в коде атрибутов, а вообще из всех доступных для данного элемента атрибутов, даже если их нет в коде. Сюда включены глобальные атрибуты и атрибуты событий
. Такие свойства принимают значения по умолчанию
.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><input name="field" value="data"></p> </body> </html> <script> var input = document.querySelector('input'); alert(input.hasAttribute('type')); /* false, атрибута type нет */ alert('type' in input); /* true, свойство type есть */ alert(input.type); /* text, значение по умолчанию */ </script>
При построении документа одноимённые атрибуты и свойства не всегда имеют одинаковое значение.
Самый распространённый пример - это атрибут href
.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><a href="home.html">Домой</a></p> </body> </html> <script> var anch = document.querySelector('a'); alert(anch.getAttribute('href')); /* home.html */ alert(anch.href); /* http://web-gain.ru/home.html */ </script>
Свойство href
всегда содержит полный (абсолютный) адрес ссылки. Это же касается и свойства src
.
Для атрибута булевого
типа (hidden
, autofocus
, checked
, disabled
, multiple
, readonly
, required
) создаётся одноимённое свойство также булевого
типа, то есть со значением true
или false
. Но в HTML-коде эти атрибуты вообще могут не иметь значений.
Если в HTML-коде будет указан нестандартный для конкретного элемента атрибут, то одноимённое свойство создано не будет.
И это логично, если атрибут не описан в стандарте, значит он не может повлиять на параметры элемента.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><a href="home.html" something="data">Домой</a></p> </body> </html> <script> var anch = document.querySelector('a'); alert(anch.hasAttribute('something')); /* true, атрибут something есть */ alert('something' in anch); /* false, свойства something нет */ </script>
Проблем с этой особенностью обычно не возникает, так как нестандартные атрибуты почти не используются (с ними страница не проходит валидацию).
Атрибуты data-
dataset
Для передачи информации в HTML введены атрибуты с префиксом data-
. С такими атрибутами нужно работать через свойство dataset
. Оно содержит список всех data-
атрибутов элемента.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><input type="text" data-some-info="something"></p> </body> </html> <script> var input = document.querySelector('input'); alert(input.dataset.someInfo); /* something */ </script>
Атрибут class
className
Свойства с именем class
не существует, так как это зарезервированное слово в JavaScript. Атрибуту class
соответствует свойство className
.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p class="first second"></p> </body> </html> <script> var par = document.querySelector('p'); alert(par.className); /* 'first second' */ </script>
Данное свойство удобно использовать, если элементу присвоен только один класс. Но если их несколько, то с этим свойством работать сложнее. Для таких случаев в DOM введено ещё одно свойство для работы с классами - classList
.
classList
Свойство classList
содержит список (псевдомассив) классов элемента. Для работы с этим массивом можно воспользоваться циклом или встроенными методами:
element.classList.add(класс)
- Добавляет класс, если такой класс отсутствует.
element.classList.remove(класс)
- Удаляет класс. Если такого класса нет, метод не выдаст ошибку.
element.classList.contains(класс)
- Проверяет, имеется ли указанный класс.
element.classList.toggle(класс)
- Добавляет класс, если его нет (и возвращает
true
), или удаляет его, если он уже есть (и возвращаетfalse
). element.classList.replace(старый_класс, новый_класс)
- Заменяет указанный класс на новый.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p class="first second"></p> </body> </html> <script> var par = document.querySelector('p'); par.classList.remove('second'); par.classList.add('third'); alert(par.className); /* 'first third' */ par.classList.toggle('third'); alert(par.classList.contains('third')); /* false */ </script>
Атрибут style
style
Свойство style
содержит объект-коллекцию всех CSS-свойств элемента. При этом значения имеют только те свойства, которые заданы атрибутом style
. Значениями остальных свойств являются пустые строки.
Использование этого свойства очень удобно, так как CSS-свойства элемента, заданные с его помощью, имеют почти самый высокий приоритет (как и атрибут style
).
Ещё одним достоинством является то, что с каждым CSS-свойством можно работать отдельно. Свойство style
представляет объект, в котором каждому свойству соответствует определённый CSS-стиль.
Кроме того, свойству style
можно присвоить стили в виде строки, как это делается с атрибутом style
. Для этого используется доступное для записи свойство style.cssText
. Однако, необходимо помнить, что присвоение нового значения свойству style.cssText
полностью перезаписывает значение атрибута style
.
<html> <head> <title>DOM интерфейс</title> </head> <body> <p><input type="text" value="Текст" style="border: 5px solid red;"></p> </body> </html> <script> var input = document.querySelector('input'); alert(input.style.border); /* 5px solid red */ alert(input.style.borderWidth); /* 5px, отдельные свойства тоже присвоены */ input.style.cssText = 'color: red; font-size: 200%'; /* изменили атрибут style */ alert(input.style.color); /* red */ </script>
Свойство style
очень полезно в случаях, когда нужно изменить какое-нибудь CSS-свойство элемента. Но оно не годится для получения значений применённых стилей. Так получается, потому что свойство style
получает значения стилей из атрибута style
, который используется редко (чаще всего CSS-стили выносятся в отдельный файл).
Чтобы получить значения всех CSS-свойств, применённых к элементу, необходимо воспользоваться методом window.getComputedStyle()
.
getComputedStyle()
Метод getComputedStyle()
объекта window
возвращает такой же объект, как и свойство style
. Но в нём содержатся значения всех стилей, которые в данный момент применены к элементу (с учётом внешних файлов стилей и тега <style>
).
window.getComputedStyle(элемент[, псевдоэлемент])
- элемент
- Исследуемый элемент (обязательно узел
элемент
, иначе выдаст ошибку). - псевдоэлемент
- Необязательный аргумент. Позволяет указать псевдоэлемент (
::after
,::before
,::first-letter
,::first-line
), чьи стили необходимо получить.
<html> <head> <title>DOM интерфейс</title> <style> p { font-size: 20px; } p::first-letter { font-size: 30px; } </style> </head> <body> <p>Lorem ipsum dolor...</p> </body> </html> <script> var par = document.querySelector('p'); var style = window.getComputedStyle(par); var style_pseudo = window.getComputedStyle(par, '::first-letter'); alert(style.fontSize); /* 20px */ alert(style_pseudo.fontSize); /* 30px */ </script>
Объект, получаемый данным методом, доступен только для чтения, поэтому с его помощью нельзя поменять стили у элемента. Для замены стилей нужно использовать свойство style
элемента.