Зарегистрируйтесь, чтобы продолжить обучение

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

Самая большая часть DOM API сосредоточена в свойствах конкретных элементов. В этом уроке мы рассмотрим только самые базовые свойства, чтобы показать, как они работают в принципе.

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

Так выглядит HTML атрибут="значение":

Атрибуты и свойства

Так выглядит DOM свойство:значение:

Атрибуты и свойства

Атрибуты

У каждого тега в 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, а значит доступен через innerHTML. А вот многие свойства не имеют соответствующих атрибутов. Например, у тега <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-дерева. Например, если мы добавим атрибут href в тег p, то он будет проигнорирован. При этом мы все еще сможем извлечь его через 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-дереву, не нужно запоминать все особенности поведения атрибутов и свойств. Как правило, понимание приходит на практике во время экспериментов методом проб и ошибок.


Дополнительные материалы

  1. Как добавить в html-элемент несколько классов?

Аватары экспертов Хекслета

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

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

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

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

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

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

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

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Верстка на HTML5 и CSS3, Программирование на JavaScript в браузере, разработка клиентских приложений используя React
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на JavaScript в браузере и на сервере (Node.js), разработка бекендов на Fastify и фронтенда на React
16 месяцев
с нуля
Старт 26 декабря
профессия
новый
Git, JavaScript, Playwright, бэкенд-тесты, юнит-тесты, API-тесты, UI-тесты, Github Actions, HTTP/HTTPS, API, Docker, SQL
8 месяцев
c опытом
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

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

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»