TGViewer
<divelopers> <divelopers> @alexnozer_dev · 1.18K subscribers
Post #408 211
Реализация пользовательских атрибутов

Под конец прошлого года я рассказывал об API пользовательских атрибутов, который предложен на замену отклонённых Apple настраиваемых встроенных элементов (Customized Built-In Elements). Это часть API веб-компонентов.

В Chrome и Firefox можно описать такой пользовательский элемент, который будет наследоваться от встроенного элемента, например кнопки, заголовка или абзаца. С помощью атрибута is пользовательский элемент связывается со встроенным.

Это позволяет сохранять поведение и семантику встроенных элементов HTML, но расширять их возможности и добавлять новое поведение. Apple категорически от этого отказались и Safari никогда не будет поддерживать эту возможность.

Пользовательских атрибуты предложены как альтернатива. На днях Кит Сиркель представил полифил пользовательских атрибутов, дополнив тем, что хотел бы видеть это в браузерах. А это значит, что скоро мы увидим прототип в Firefox.

Пользовательские атрибуты похожи на пользовательские элементы способом описания, регистрацией и жизненным циклом. Но с атрибутами можно расширять существующие элементы не вводя новые. Идея похожа на атрибут is.

Дисклеймер: это обзор раннего предложения новых функций. Синтаксис может измениться в будущем или от функций могут отказаться


В примере к полифилу приводится атрибут persist-value, который вешает слушатель события input и записывает значение элемента в LocalStorage. В роли ключа используется значение атрибута. Такой атрибут применим к разным полям ввода.

class PersistValue extends Attr {
connectedCallback() {
const stored = localStorage.getItem(
this.value
);
if (stored !== null) {
this.ownerElement.value = stored;
}
this
.ownerElement
.addEventListener(
"input",
this
);
}

disconnectedCallback() {
this
.ownerElement
.removeEventListener(
"input",
this
);
}

attributeChangedCallback(oldValue, newValue) {
if (oldValue !== null) {
localStorage.removeItem(oldValue);
}
}

handleEvent() {
localStorage.setItem(
this.value,
this.ownerElement.value
);
}
}

customAttributes.define(
"persist-value",
PersistValue
);


Использование в HTML:

<input
name="email"
persist-value="email-draft"
>
<textarea
name="bio"
persist-value="bio-draft"
>
</textarea>


Такой API выглядит интереснее, чем is как минимум по двум причинам. Первая: у одного элемента можно указать сразу несколько разных атрибутов. В is можно указать только имя одного конкретного пользовательского элемента.

Вторая: один атрибут можно применить к разным элементам из-за наследования от Attr. В is можно указать имя только того пользовательского элемента, который наследуется от соответствующего типа встроенного элемента.

Пользовательские атрибуты дадут авторам HTML-first библиотек более удобный способ связывания атрибутов с элементами и возможность реагирования на события жизненного цикла. Кроме того, это способ расширять стандартные элементы.

Вместе с полифилом есть ссылка на эксплейнер, в котором подробнее описан предлагаемый API. Также есть страницы с описанием мотивации и дизайна API. Я заинтересован и буду ждать появления прототипа в Firefox.

#html #js #web_api
  • 👍 4
  • 🤝 1
More from @alexnozer_dev
  1. Sep 14, 2026Подклассы Event вместо CustomEvent Многие библиотеки предоставляют систему событий в качес…
  2. Sep 11, 2026Эволюция стилей в темах Shopify Адам Ватан на днях поделился новостью, что Shopify выкупил…
  3. Sep 9, 2026Persistent Widgets Многие сайты не должны быть SPA. Но иногда эта архитектура продиктована…
  4. Sep 7, 2026Processing Instructions и маркеры В DOM всё представлено в виде узлов (Node) разных типов.…
  5. Sep 1, 2026@scope и потоковая передача HTML Ноам Розенталь поделился интересной техникой, в которой с…
  6. Aug 26, 2026Не стоит полагаться на User Agent User Agent sniffing — это техника поиска в строке User A…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →