Свойства и атрибуты #
Атрибуты — то, что записано в HTML (disabled, data-track-id). Свойства — поля JavaScript-объекта элемента; они могут расходиться с разметкой (например, value у <input>). Для UI JSFlow атрибуты data-* и классы часто хранят состояние, а свойства — отражают интерактивность формы.
Чтение и запись атрибутов #
const emailInput = document.querySelector('#checkout-email')
emailInput.getAttribute('type') // "email"
emailInput.setAttribute('aria-invalid', 'true')
emailInput.removeAttribute('readonly')
emailInput.hasAttribute('required') // true
getAttribute всегда возвращает строку или null. Булевы атрибуты в HTML (disabled, checked) присутствуют как пустая строка или имя атрибута:
const payBtn = document.querySelector('#pay-now')
payBtn.getAttribute('disabled') // "" если выключена, null если нет атрибута
Свойства vs атрибуты #
const qtyInput = document.querySelector('#item-qty')
qtyInput.value = '5' // свойство — текущее значение в поле
qtyInput.defaultValue // значение из исходного HTML
qtyInput.setAttribute('value', '1') // не меняет то, что видит пользователь, если value уже меняли
Типичные пары:
| Элемент | Атрибут | Свойство | Заметка |
|---|---|---|---|
| input | value | .value | свойство — актуальный ввод |
| input | checked | .checked | чекбокс |
| button | disabled | .disabled | boolean-свойство |
| img | src | .src | свойство может быть абсолютным URL |
Для форм checkout опирайтесь на .value, .checked, .disabled — они синхронизированы с UI.
dataset и data-* #
Атрибуты data-* доступны через element.dataset; имена в camelCase:
<li class="track-row" data-track-id="tr-884" data-duration-sec="214">
const row = document.querySelector('.track-row')
row.dataset.trackId // "tr-884"
row.dataset.durationSec // "214" — всегда строка
row.dataset.playing = 'true'
// в DOM: data-playing="true"
Удаление:
delete row.dataset.playing
data-* удобны для делегирования: в обработчике читайте event.target.closest('[data-track-id]')?.dataset.trackId.
id и class #
const modal = document.querySelector('.checkout-modal')
modal.id = 'step-shipping' // обновит атрибут id
modal.className = 'checkout-modal is-open' // перезапишет все классы
Для точечных изменений используйте classList (подробнее в Стили и координаты):
modal.classList.add('is-open')
modal.classList.remove('is-hidden')
modal.classList.toggle('is-loading', formPending)
modal.classList.contains('is-open') // true
ARIA и доступность #
Состояние виджета дашборда можно отразить для скринридеров:
const widget = document.querySelector('[data-widget="orders"]')
widget.setAttribute('role', 'region')
widget.setAttribute('aria-label', 'Заказы за сегодня')
widget.setAttribute('aria-busy', 'true')
// после загрузки данных
widget.setAttribute('aria-busy', 'false')
Не дублируйте видимый текст в aria-label, если заголовок уже связан через aria-labelledby.
Практика: состояние плейлиста #
function markPlaying(trackId) {
document.querySelectorAll('.track-row').forEach((row) => {
const isActive = row.dataset.trackId === trackId
row.classList.toggle('is-playing', isActive)
row.setAttribute('aria-current', isActive ? 'true' : 'false')
})
}
markPlaying('tr-884')
Итог #
- Атрибуты — строки в разметке; свойства — живое состояние элемента.
- Формы: читайте
.value,.checked,.disabled. data-*иdataset— лёгкий способ хранить ID и флаги без лишних классов.classListпредпочтительнее присваиванияclassNameцеликом.