DOM, часть 4 из 4. Атрибуты и свойства
При написании HTML-кода мы можем задавать атрибуты для атрибуты HTML-элементов. Атрибуты могут быть стандартными и нестандартными, причем стандартный атрибут для одного тега может быть нестандартным для другого. Например, атрибут type является стандартным для элемента , но не является стандартным для .
Все атрибуты доступны с помощью следующих методов:
- elem.hasAttribute(name) — проверяет наличие атрибута
- elem.getAttribute(name) — получает значение атрибута
- elem.setAttribute(name, value) — устанавливает значение атрибута
- elem.removeAttribute(name) — удаляет атрибут
Эти методы работают именно с тем, что мы написали в HTML-коде. Имена HTML-атрибутов регистронезависимы, а значения всегда являются строками. Получить все атрибуты элемента можно с помощью свойства elem.attributes — это коллекция объектов, которая принадлежит ко встроенному классу Attr со свойствами name и value .
id="content" something="some value"> // имя атрибута не завистит от регистра if (document.body.hasAttribute('ID')) alert(document.body.getAttribute('id')); // content > // пример чтения нестандартного атрибута alert(document.body.getAttribute('something')); // some value // добавим еще один атрибут для body document.body.setAttribute('style', 'background:yellow'); // покажем весь список атрибутов body for (let attr of document.body.attributes) alert(`$ = $ `); >
DOM-свойства
Когда браузер загружает страницу, он «читает» HTML-код и генерирует из него DOM-объекты. Для узлов-элементов большинство стандартных HTML-атрибутов автоматически становятся свойствами DOM-объектов. Например, для тега у DOM-объекта будет такое свойство body.id=»page» .
DOM-узлы — это обычные объекты JavaScript, мы можем их изменять:
document.body.something = name: 'some name', value: 'some value' >;
document.body.sayTagName = function() alert(this.tagName); >;
Синхронизация атрибутов и свойств
Когда стандартный атрибут изменяется, соответствующее свойство автоматически обновляется. Это работает и в обратную сторону (за некоторыми исключениями).
let input = document.querySelector('input'); // атрибут => свойство input.setAttribute('id', 'email'); alert(input.id); // email (обновлено) // свойство => атрибут input.id = 'phone'; alert(input.getAttribute('id')); // phone (обновлено)
let input = document.querySelector('input'); // атрибут => свойство input.setAttribute('value', 'значение'); alert(input.value); // значение // свойство => атрибут input.value = 'новое значение'; alert(input.getAttribute('value')); // значение (не обновилось!)
- Изменение атрибута value обновило свойство
- Но изменение свойства не повлияло на атрибут
Иногда эта «особенность» может пригодиться, потому что действия пользователя могут приводить к изменениям value , и если после этого мы захотим восстановить «оригинальное» значение из HTML-кода, оно будет в атрибуте.
DOM-свойства типизированы
DOM-свойства не всегда являются строками. Например, свойство input.checked (для чекбоксов) имеет логический тип.
id="input" type="checkbox" checked> alert(input.getAttribute('checked')); // значение атрибута — пустая строка alert(input.checked); // значение свойства — логическое true
Есть и другие примеры. Атрибут style — строка, но свойство style является объектом:
id="div" style="color:red;font-size:120%">Hello // атрибут style — строка alert(div.getAttribute('style')); // color:red;font-size:120% // свойство style — объект alert(div.style); // [object CSSStyleDeclaration] alert(div.style.color); // red
Хотя большинство свойств, всё же, строки. При этом некоторые из них, хоть и строки, могут отличаться от атрибутов. Например, DOM-свойство href всегда содержит полный URL, даже если атрибут содержит относительный URL или просто #hash .
id="link" href="#hello">Ссылка // атрибут href alert(link.getAttribute('href')); // #hello // свойство href alert(link.href); // полный URL в виде http://site.com/some/path#hello
Если же нужно значение href или любого другого атрибута в точности, как оно записано в HTML-коде, можно воспользоваться getAttribute .
Нестандартные атрибуты, dataset
При написании HTML-кода мы используем много стандартных атрибутов. Но что насчёт нестандартных, пользовательских? Они тоже часто нужны — например, для передачи пользовательских данных из HTML-кода в JavaScript, или чтобы «помечать» HTML-элементы для JavaScript.
show-info="name"> show-info="age"> // код находит элемент с пометкой и показывает информацию let user = name: 'Сергей', age: 25 >; for (let div of document.querySelectorAll('[show-info]')) // вставить соответствующую информацию в поле let field = div.getAttribute('show-info'); div.textContent = user[field]; >
Но с пользовательскими атрибутами могут возникнуть проблемы. Что если мы используем нестандартный атрибут для наших целей, а позже он появится в стандарте и будет выполнять какую-то функцию? Чтобы избежать конфликтов, были придуманы data -атрибуты, доступ к значениям которых из js-кода возможен через dataset .
id="user" data-name="Сергей" data-age="25"> alert(user.dataset.name); // Сергей alert(user.dataset.age); // 25
className и classList
Изменение класса является одним из наиболее часто используемых действий в скриптах. Атрибут class в HTML-коде соответствует атрибуту className элемента.
class="main page"> alert(document.body.className); // main page
Если мы присваиваем что-то elem.className , то это заменяет всю строку с классами. Иногда это то, что нам нужно, но часто мы хотим добавить или удалить один класс. Для этого есть другое свойство — elem.classList .
class="main page"> // добавление css-класса для body document.body.classList.add('article'); alert(document.body.className); // main page article
Так что мы можем работать как со строкой полного класса, используя className , так и с отдельными классами, используя classList .
- elem.classList.add(class) — добавить css-класс
- elem.classList.remove(class) — удалить css-класс
- elem.classList.toggle(class) — добавить css-класс, если его нет, иначе — удалить
- elem.classList.contains(class) — проверка наличия css-класса, возвращает true или false
Кроме того, classList является перебираемым, поэтому можно перечислить все классы при помощи цикла:
class="main page"> for (let name of document.body.classList) alert(name); // main, page >
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
- 1С:Предприятие (31)
- API (29)
- Bash (43)
- CLI (100)
- CMS (139)
- CSS (50)
- Frontend (75)
- HTML (66)
- JavaScript (150)
- Laravel (72)
- Linux (147)
- MySQL (76)
- PHP (125)
- React.js (66)
- SSH (27)
- Ubuntu (68)
- Web-разработка (509)
- WordPress (73)
- Yii2 (69)
- БазаДанных (95)
- Битрикс (66)
- Блог (29)
- Верстка (43)
- ИнтернетМагаз… (84)
- КаталогТоваров (87)
- Класс (30)
- Клиент (27)
- Ключ (28)
- Команда (69)
- Компонент (60)
- Конфигурация (62)
- Корзина (32)
- ЛокальнаяСеть (28)
- Модуль (34)
- Навигация (31)
- Настройка (140)
- ПанельУправле… (29)
- Плагин (33)
- Пользователь (26)
- Практика (99)
- Сервер (74)
- Событие (27)
- Теория (105)
- Установка (66)
- Файл (47)
- Форма (58)
- Фреймворк (192)
- Функция (36)
- ШаблонСайта (68)