Learn JavaScript

Атрибуты, классы и dataset в DOM

Когда JavaScript управляет страницей, чаще всего меняются три вещи:

  • атрибуты (href, src, disabled, value, aria-, data-)
  • классы (для переключения стилей)
  • data-атрибуты (для хранения меток и параметров прямо в HTML)

1) Атрибуты: что это и как с ними работать

Атрибуты - это часть HTML-разметки:

<a href="/about" class="link">About</a>
<img src="/img/logo.png" alt="Logo">
<input type="checkbox" checked>

Чтение и запись через getAttribute/setAttribute

const link = document.querySelector("a");

const href = link.getAttribute("href");
console.log(href); // например "/about"

link.setAttribute("href", "/contacts");

Удаление атрибута:

const img = document.querySelector("img");

img.removeAttribute("alt");

Атрибуты vs свойства (property)

У многих атрибутов есть DOM-свойства: value, checked, disabled, href, src. Иногда удобнее работать именно со свойствами.

const input = document.querySelector("input[type='text']");

input.value = "Hello";
console.log(input.value);

Для ссылок:

const link = document.querySelector("a");

console.log(link.getAttribute("href")); // то, что в HTML
console.log(link.href);                 // абсолютный URL, вычисленный браузером

Оба варианта полезны, просто они отвечают на разные вопросы.

2) Булевые атрибуты: checked, disabled, hidden

Булевой атрибут считается включенным уже от самого факта наличия в HTML.

HTML:

<button disabled>Save</button>

JavaScript - удобнее через свойства:

const btn = document.querySelector("button");

btn.disabled = true;
btn.disabled = false;

Аналогично с чекбоксом:

const checkbox = document.querySelector("input[type='checkbox']");

checkbox.checked = true;
checkbox.checked = false;

3) Классы: classList

Классы используют для управления состоянием через CSS: “открыто”, “активно”, “ошибка”, “загрузка”.

const modal = document.querySelector(".modal");

modal.classList.add("is-open");
modal.classList.remove("is-open");
modal.classList.toggle("is-open");
console.log(modal.classList.contains("is-open"));

Замена класса

const btn = document.querySelector(".btn");

btn.classList.replace("btn--primary", "btn--secondary");

Установка className целиком

Иногда нужно заменить все классы:

const box = document.querySelector(".box");

box.className = "box box--big";

Это работает, но часто удобнее classList, чтобы случайно не стереть нужные классы.

4) data-* атрибуты: зачем они нужны

data-* - это стандартный способ хранить небольшие данные прямо в HTML. Например, id, тип действия, роль, параметры.

HTML:

<button class="btn" data-action="save" data-id="42">Save</button>

JavaScript:

const btn = document.querySelector(".btn");

console.log(btn.dataset.action); // "save"
console.log(btn.dataset.id);     // "42"

Важно: dataset всегда возвращает строки.

5) Как работают имена в dataset

data-user-id превращается в dataset.userId (kebab-case -> camelCase).

HTML:

<div class="card" data-user-id="7" data-item-type="book"></div>

JavaScript:

const card = document.querySelector(".card");

console.log(card.dataset.userId);   // "7"
console.log(card.dataset.itemType); // "book"

Запись:

card.dataset.userId = "10";

Это обновит атрибут data-user-id в DOM.

6) Приведение типов при работе с dataset

Так как dataset хранит строки, для чисел и булевых значений обычно делают преобразование.

const btn = document.querySelector("[data-count]");

const count = Number(btn.dataset.count);
console.log(count);

Булевый флаг часто делают строками "true" / "false":

const el = document.querySelector("[data-active]");

const isActive = el.dataset.active === "true";
console.log(isActive);

7) Практичный мини-паттерн: action через dataset

Частый сценарий - кнопки с действиями:

HTML:

<button data-action="open">Open</button>
<button data-action="close">Close</button>

JavaScript (пока без событий, только чтение):

const buttons = document.querySelectorAll("[data-action]");

buttons.forEach((btn) => {
  console.log(btn.dataset.action);
});

Такую разметку легко расширять: добавляется кнопка - добавляется data-action.

Частые ошибки

1) Ожидание, что dataset вернет число

const el = document.querySelector("[data-id]");

console.log(typeof el.dataset.id); // "string"

Если нужен number, нужен Number(...).

2) Работа с классами через className и потеря классов

const el = document.querySelector(".box");

el.className = "active";

Так стираются все остальные классы. Если нужен один класс дополнительно, лучше:

const el = document.querySelector(".box");

el.classList.add("active");

3) Попытка включить булевой атрибут значением “false”

const btn = document.querySelector("button");

btn.setAttribute("disabled", "false");
console.log(btn.disabled); // true

Булевой атрибут включается наличием. Правильнее:

const btn = document.querySelector("button");

btn.disabled = false;

Что стоит запомнить

  • Атрибуты читаются через getAttribute, задаются через setAttribute, удаляются через removeAttribute.
  • Для value, checked, disabled часто удобнее DOM-свойства.
  • Классы лучше менять через classList.
  • data-* и dataset удобны для хранения небольших меток в HTML, но значения там всегда строки.