Самая большая часть DOM API сосредоточена в свойствах конкретных элементов. В этом уроке мы рассмотрим только самые базовые свойства, исключительно с целью показать то, как они работают в принципе. В повседневной практике программисты постоянно обращаются к документации, чтобы узнать, какие есть свойства и методы у узлов для управления ими.
У каждого тега в HTML есть атрибуты. Некоторые из них общие для всех, другие специфичные для конкретных тегов.
<a id="aboutPage" href="/pages/about" class="simple">About</a>
В примере выше, атрибуты id
и class
могут использоваться с любым тегом. Атрибут href
только с некоторыми, например, с тегом <a>
.
Когда браузер загрузил HTML, на его основе строится DOM. Во время обработки, каждый тег становится узлом, а атрибуты – свойствами этого узла. Обычно имена атрибутов и свойств узлов совпадают между собой:
// <a id="aboutPage" href="/pages/about" class="simple">About</a>
const el = document.querySelector('#aboutPage');
el.id; // aboutPage
el.href; // https://ru.hexlet.io/pages/about
Существуют и исключения, например, атрибуту class
соответствует свойство className
. Более того, для удобной работы с классами предусмотрены дополнительные способы работы. Это нужно по той причине, что классов может быть много и задаются они обычной текстовой строкой. Соответственно, если возникает задача изменения этого списка, то придется оперировать строчками, что совсем неудобно. А вот как можно это делать, используя возможности DOM:
// У тега с таким id класс содержит строку "simple"
const el = document.querySelector('#aboutPage');
el.classList.add('page');
el.classList.remove('simple');
// После всех изменений
el.className; // page
Дополнительные методы:
el.classList.contains("class")
– проверяет содержит ли элемент нужный класс. Возвращает true/false.el.classList.toggle("class")
– если класс есть, удаляет его, и наоборот.Именование – не единственное различие между атрибутами и свойствами. Отличий значительно больше и они не всегда очевидны. Вот лишь некоторые из них:
Атрибут — всегда строка, а свойство — не всегда. Например:
<textarea rows="5"></textarea>
Значение свойства rows
соответствующего элемента в DOM дереве будет числом.
Атрибуты не чувствительны к регистру
<a Id="aboutPage" hrEf="/pages/about" CLASS="simple">About</a>
Так писать, конечно же, не стоит, но по крайней мере знать о том, что оно работает - полезно.
Атрибут всегда присутствует в HTML, а значит доступен через innerHTML
. А вот многие свойства не имеют соответствующих атрибутов. Например у тега <a>
есть свойство hash
, но нет такого атрибута.
Как мы увидели выше, атрибут и свойство, в общем случае — не одно и то же. Поэтому существует набор методов для управления атрибутами:
el.hasAttribute(name)
– проверяет наличие атрибутаel.getAttribute(name)
– получает значение атрибутаel.setAttribute(name, value)
– устанавливает атрибутel.removeAttribute(name)
– удаляет атрибутel.attributes
– список html атрибутов// Методы работают с атрибутами html
el.getAttribute('class');
Обратите внимание на то, что они работают именно с атрибутами (их именами), а не свойствами. И позволяют не только их извлекать, но и менять. Возникает закономерный вопрос: поменяется ли атрибут, если поменять свойство и наоборот?
В основном синхронизация осуществляется только в сторону свойств. То есть меняется атрибут и автоматически обновляется свойство. Но существуют и исключения. Из этих тезисов не следует делать вывод, что нужно стараться работать через атрибуты. Наоборот, по возможности, всегда работайте со свойствами дом дерева, а атрибуты используйте только для чтения, чтобы получить то состояние, которое было в DOM на момент инициализации (парсинга HTML).
<a id="aboutPage" href="/pages/about" class="simple">About</a>
const el = document.querySelector('#aboutPage');
el.setAttribute('class', 'page');
el.className; // page
el.getAttribute('class'); // page
В отличие от свойств значение атрибута всегда совпадает с тем, что мы видим в HTML, а вот свойства иногда приводятся в нормализованный вид:
<!-- В этот момент браузер открыт на https://ru.hexlet.io -->
<a id="link-to-courses" href="/courses">Курсы</a>
const el = document.querySelector('#link-to-courses');
el.href; // https://ru.hexlet.io/courses
el.getAttribute('href'); // /courses
Нестандартные атрибуты никогда не превращаются в свойства соответствующих элементов DOM дерева. То есть, если мы добавим в тег p
атрибут href
, то он будет проигнорирован. Хотя это не отменяет возможность его извлечения через getAttribute
.
Для работы с произвольными свойствами в html зарезервирован специальный атрибут data-*
, где на месте звездочки может стоять любое слово.
<a href="#" data-toggle="tab">Мои проекты</a>
Такие атрибуты активно используются в JavaScript плагинах и позволяют не завязываться на классы. В элементах DOM они доступны через специальное свойство dataset
:
console.log(el.dataset.toggle); // => tab
Внутри объекта dataset
имя каждого свойства — это строка после data-
в атрибуте. Если имя содержит дефис, то он удаляется, а следующая за ним буква становится заглавной:
<a href="#" data-nav-toggle="tab">Мои проекты</a>
console.log(el.dataset.navToggle); // => tab
В зависимости от типа элемента меняется и набор свойств. Кроме, конечно, тех, что достались в наследство от Node и Element.
Чтобы узнать список этих свойств, можно обращаться к спецификации. Они описаны в специальном формате, который несложно понять:
// HTMLLinkElement – Просто название интерфейса
// HTMLElement – родительский тип, от которого наследуются свойства и методы
// attribute – обозначение конкретного атрибута, его типа и имени
interface HTMLLinkElement : HTMLElement {
// Последнее слово в каждой строке это имя свойства в объекте
attribute USVString href;
attribute DOMString? crossOrigin;
attribute DOMString rel;
attribute RequestDestination as; // (default "")
readonly attribute DOMTokenList relList;
attribute DOMString media;
attribute DOMString nonce;
attribute DOMString integrity;
attribute DOMString hreflang;
attribute DOMString type;
}
Как и в случае с навигацией по DOM-дереву, нет нужды запоминать все особенности поведения атрибутов и свойств. Как правило, хорошее понимание приходит на практике во время экспериментов, методом проб и ошибок.
Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт