Управление узлами DOM JS: DOM API

Самая большая часть 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") – если класс есть, удаляет его, и наоборот.

Именование – не единственное различие между атрибутами и свойствами. Отличий значительно больше и они не всегда очевидны. Вот лишь некоторые из них:

  1. Атрибут — всегда строка, а свойство — не всегда. Например:

    <textarea rows="5"></textarea>
    

    Значение свойства rows соответствующего элемента в DOM дереве будет числом.

  2. Атрибуты не чувствительны к регистру

    <a Id="aboutPage" hrEf="/pages/about" CLASS="simple">About</a>
    

    Так писать, конечно же, не стоит, но по крайней мере знать о том, что оно работает — полезно.

  3. Атрибут всегда присутствует в HTML, а значит доступен через outerHTML. А вот многие свойства не имеют соответствующих атрибутов. Например у тега <a> есть свойство hash, но нет такого атрибута.

Как мы увидели выше, атрибут и свойство, в общем случае — не одно и то же. Поэтому существует набор методов для управления атрибутами:

  • el.hasAttribute(name) – проверяет наличие атрибута
  • el.getAttribute(name) – получает значение атрибута
  • el.setAttribute(name, value) – устанавливает атрибут
  • el.removeAttribute(name) – удаляет атрибут
  • el.attributes – список html атрибутов
// Методы работают с атрибутами html
el.getAttribute('class');

Обратите внимание на то, что они работают именно с атрибутами (их именами), а не свойствами. И позволяют не только их извлекать, но и менять. Возникает закономерный вопрос: поменяется ли атрибут, если поменять свойство и наоборот?

В основном синхронизация осуществляется только в сторону свойств. То есть меняется атрибут и автоматически обновляется свойство. Но существуют и исключения. Из этих тезисов не следует делать вывод, что нужно стараться работать через атрибуты. Наоборот, по возможности, всегда работайте со свойствами DOM-дерева, а атрибуты используйте только для чтения, чтобы получить то состояние, которое было в 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-дереву, нет нужды запоминать все особенности поведения атрибутов и свойств. Как правило, хорошее понимание приходит на практике во время экспериментов, методом проб и ошибок.


<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
120
курсов
900
упражнения
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 120 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Фронтенд-разработчик
Профессия

Фронтенд-разработчик

Разработка фронтенд-компонентов веб-приложений
16 июня 8 месяцев

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».