data-атрибуты (dataset)

data-* — HTML-атрибуты для хранения произвольных пользовательских данных прямо в элементе; доступны из JavaScript через свойство element.dataset.

Зачем нужно

data-атрибуты позволяют связать данные с DOM-элементом декларативно, прямо в разметке, без внешних структур данных. Это удобно для делегирования событий, хранения идентификаторов, конфигурации компонентов и передачи данных из шаблонизатора в JavaScript.

Где используется

  • Хранение ID сущности (товара, пользователя) прямо в элементе
  • Конфигурация UI-компонентов через HTML (tooltips, слайдеры, модалки)
  • Передача данных при делегировании событий
  • Хранение состояния элемента (выбран, раскрыт, загружается)

Синтаксис

HTML использует kebab-case: data-user-id, JavaScript читает через camelCase: dataset.userId.

<button
  data-user-id="42"
  data-user-name="Иван"
  data-role="admin"
>
  Удалить
</button>
const btn = document.querySelector('button');

// Чтение
console.log(btn.dataset.userId);   // "42"  (всегда строка!)
console.log(btn.dataset.userName); // "Иван"
console.log(btn.dataset.role);     // "admin"

// Запись
btn.dataset.status = 'active';
// В HTML появится data-status="active"

// Удаление
delete btn.dataset.role;

Практические примеры

Делегирование событий с данными

const list = document.querySelector('.product-list');

list.addEventListener('click', (event) => {
  const btn = event.target.closest('[data-action]');
  if (!btn) return;

  const { action, productId } = btn.dataset;

  if (action === 'add-to-cart') {
    addToCart(productId);
  } else if (action === 'delete') {
    deleteProduct(productId);
  }
});
<li>
  Товар A
  <button data-action="add-to-cart" data-product-id="101">В корзину</button>
  <button data-action="delete" data-product-id="101">Удалить</button>
</li>

Конфигурация компонента

document.querySelectorAll('[data-tooltip]').forEach(el => {
  el.addEventListener('mouseenter', () => {
    showTooltip(el, el.dataset.tooltip, el.dataset.tooltipPosition || 'top');
  });
});

Состояние элемента

const accordion = document.querySelector('.accordion');

accordion.addEventListener('click', (event) => {
  const header = event.target.closest('.accordion__header');
  if (!header) return;

  const isOpen = header.dataset.open() === 'true';
  header.dataset.open() = String(!isOpen);

  header.nextElementSibling.hidden = isOpen;
});

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

  • Забыть, что dataset возвращает строки — числа нужно явно преобразовывать: Number(el.dataset.count) или parseInt(el.dataset.count, 10).
  • Хранить большие или сложные данные — dataset не предназначен для объектов; для сложных данных лучше использовать Map или WeakMap с элементом в качестве ключа.
  • Имена с заглавных букв в HTMLdata-UserName невалидно; все буквы в HTML-атрибуте строчные.

Связанные темы

Ресурсы