Когда 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, но значения там всегда строки.