В предыдущей статье об основах JS мы рассмотрели селекторы HTML элементов, теперь нужно разобраться как манипулировать элементами, после того как они будут найдены. Важной частью этой работы, является взаимодействие с атрибутами HTML элементов.
Немного базы
Атрибуты это пары ключ значения которые находятся прямо в дескрипторе HTML тега:
<div class="someClass"></div>
Множество атрибутов входят в состав спецификации HTML5: какие-то просто содержат метаданные элемента (class, name, id), от каких-то зависит отображение элемента в браузере (type, checked). Но так как HTML, это всего лишь расширение спецификации языка XML, то никто нам не мешает нам придумать и внедрить свой атрибут:
<div class="someClass" my-new-attribut="Hello word"></div>
После добавления атрибута my-new-attribut в код, всё будет по-прежнему корректно отображается. Компьютер не взорвётся и даже браузера не зависнет. Правда и толку от этого новшества пока не видно. Но это только пока!
Методы для работы с атрибутами в JavaScript
Для работы с атрибутами, в JS существует несколько универсальных методов:
getAttribute()- получает значение атрибута по его имени;setAttribute()- устанавливает атрибут с указанным именем и значением;hasAttribute()- проверяет наличие атрибута с указанным именем;removeAttribute()- удаляет указанный атрибут.
Все примеры кода на JavaScript будут работать с вот такой вот простенькой HTMLькой:
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>HTML атрибуты и JavaScript</title> </head> <body> <div class="someClass main-block" name="block"> <form action="" data-action-url="some/url/"> <input type="text" name="user-name" value="Вася"> </form></div> <script src="js/script.js"></script> </body> </html>
const elem = document.querySelector('.someClass') elem.setAttribute('name', 'block') // Устанавливает атрибут name со значением block elem.getAttribute('name') // Возвращает значение block elem.hasAttribute('name') // Возвращает true, так как атрибут name существует elem.removeAttribute('name') // Удаляет атрибут name
Атрибуты как свойства HTMLElement
Со стандартными атрибутами из спецификации HTML, всё гораздо проще. Они доступны для чтения и записи как свойства объекта HTMLElement, который можно получить при помощи селекторов. Стоит учитывать что в данном объекте имена свойств, могут отличаться от имён самих атрибутов. Например, у тега поля input, имеется стандартный атрибут value, которых содержит значение введённое пользователем. В объекте HTMLElement, данный атрибут будет доступен через свойство defaultValue. Отличие в имени свойства и атрибута, позволяют избежать конфликтов с синтаксисом JavaScript.
Свойств объекта HTMLElement, в отличие от самих атрибутов, чувствительны к регистру. В объекте имена свойств всегда будут в нижнем регистре, а если имя атрибута состоит из нескольких слов, то для их написания используется нотация camelCase, за исключение свойств событий, которые записываются в нижнем регистре (onclick). Если имя атрибута совпадает с зарезервированным словом в JavaScript, то оно снабжается префиксом html, например атрибут for, в HTMLElement, доступен под именем htmlFor. Исключением из данного правила является атрибут class, доступный через свойство className.
const elem = document.querySelector('input') elem.type // text elem.defaultValue // Вася elem.name // user-name
Чаще всего, атрибут будет иметь строковое значение. Но если у атрибута предполагается булево значение (defaultChecked, maxLength), то значение свойства объекта HTMLElement, также будет булевым типом. Значение атрибутов, задающих обработчики пользовательских событий (onclick, onchange и т.д.) событий всегда равно null.
Через объект HTMLElement, никак нельзя удалить атрибут у элемента (оператор delete, не сработает), единственный способ сделать это метод removeAttribute().
Атрибут class
Работа с атрибутом class в JavaScript несколько выделяется. В свойстве className, объекта Element, все классы хранятся в виде обычной строки. Манипулировать классами элементов, работая с обычной строкой было бы крайне муторно, поэтому для этих целей в JS был добавлен отдельный интерфейс, хранящийся в свойстве classList. Он состоит из методов:
add()- добавляет новый класс элементу;remove()- удаляет указанный класс у элемента;contains()- проверяет наличие класса у элемента;toggle()- добавляет класс элементу если его нет, удаляет его если он есть.
const elem = document.querySelector('.someClass') elem.classList.add('new-class') // Добавляет класс new-class элементу elem.classList.contains('someClass') // Возвращает true elem.classList.toggle('someClass') // Удаляет someClass, возвращает false elem.classList.toggle('someClass') // Добавляем someClass, возвращает true elem.classList.remove('new-class') // Удаляет класс new-class у элемента
В самом свойстве classList, хранится объект DOMTokenList. Он является итерируемым, а значит его можно перебрать в цикле.
const elem = document.querySelector('.someClass') сssClasses = elem.classList for(let i = 0; сssClasses.length > i; i++) { // Получаем классы через сssClasses[i] }
Dataset
HTML элементам можно добавлять атрибуты набора данных, которые должны начинаться с префикса data-. Они могут хранить любые данные, и никак не влияют на внешний вид документа.
Важность этой фичи сложно переоценить, ведь в JavaScrip, для работы с данными атрибутами, реализован специальный интерфейс. Получить доступ к таким атрибутам имеющим префикс data-, можно через свойство dataset объекта Element. Там они хранятся в виде объекта со свойствами, имена которых идентичны именам атрибутов, но уже без префикса data-. Например, значение атрибута data-action-url, будет доступно в JS через свойство dataset.actionUrl:
const form = document.querySelector('form') console.log(form.dataset.actionUrl) // Будет равно: Some data
Вывод
JavaScript имеет обширный и удобный интерфейс для работы с атрибутами HTML элементов, который по традиции заведённой в JS избыточен. Знать что атрибуты доступны, в виде свойств объекта HTMLElement нужно, но использования этой методики в практическом коде, лучше избегать, дабы его не усложнять. Также не стоит использовать работу с объектом из свойства classList, в цикле. Прочесть об этом полезно, использовать в деле нет! Применяя из многообразия синтаксиса JavaScript, наиболее универсальные интерфейсы, фронтендеры могут упростить жизнь друг, другу.
