Custom Attributes؛ کاستوم المنت برای اتریبیوتها
خلاصهٔ کاملتر
نویسنده یه polyfill برای Custom Attributes منتشر کرده؛ قابلیتی که خودش رو اینطور معرفی میکنه: کاستوم المنت، ولی برای اتریبیوتها. کار کردن باهاش سادهست. یه کلاس از Attr ارث میبری، با customAttributes.define() و یه اسم خطفاصلهدار ثبتش میکنی، و از اون به بعد هر اتریبیوت همنام روی یه المنتِ متصل به صفحه، سر جاش به نمونهای از کلاس تو ارتقا (upgrade) پیدا میکنه.
تفاوتش با کاستوم المنت ساده و روشنه: کاستوم المنت میگه یه المنت چی هست، کاستوم اتریبیوت میگه چه رفتاری داره. چون رفتاره، میتونی به هر چیزی بچسبونیش: HTML، SVG، MathML یا حتی یه کاستوم المنت دیگه. مثال خود مقاله یه اتریبیوت persist-value میسازه که مقدار ورودی رو تو localStorage نگه میداره:
class PersistValue extends Attr {
connectedCallback() {
this.ownerElement.addEventListener("input", this);
}
handleEvent() {
localStorage.setItem(this.value, this.ownerElement.value);
}
}
customAttributes.define("persist-value", PersistValue);بعدش فقط مینویسی و تمام. نکتهٔ جالبش اینه که el.getAttributeNode("persist-value") خودِ همون نمونه رو برمیگردونه، پس متدهایی که به کلاس اضافه میکنی روی گرهٔ اتریبیوت میمونن و با API خود المنت قاطی نمیشن.
چرخهٔ عمرش هم دقیقاً شبیه کاستوم المنته: connectedCallback وقتی اتریبیوت روی یه المنتِ داخل صفحه اضافه میشه، disconnectedCallback وقتی برداشته میشه، و attributeChangedCallback(oldValue, newValue) با هر تغییر مقدار، که یه بار هم همون اول با مقدار اولیه صدا میخوره. دو تا کالبک کمتر دیدهشده هم داره: connectedMoveCallback برای جابهجایی المنت با moveBefore() و adoptedCallback برای وقتی المنت به یه داکیومنت دیگه منتقل میشه.
خود polyfill با یه import ساده فعال میشه، یا اگه بخوای دستی کنترلش کنی با isSupported() و apply(). چیزهایی که پوشش میده هم کم نیست: window.customAttributes، کلاس CustomAttributeRegistry و حتی رجیستریهای اسکوپدار برای shadow tree، کانستراکتور Attr، document.createAttribute() و آپشن customAttributeRegistry تو createElement() و importNode() و attachShadow() و setHTMLUnsafe().
نویسنده محدودیتها رو هم صریح میگه. واکنشها نه همزمان با عملیات DOM، بلکه تو چکپوینت microtask بعدی اجرا میشن؛ اگه یه المنت رو تو همون تَسک برداری و دوباره بذاری، اتریبیوتهاش متصل میمونن و جفت disconnected/connected صدا نمیخوره؛ و cloneNode() رجیستری رو کپی نمیکنه. یعنی اگه کدت به ترتیب دقیق کالبکها حساسه، رفتار polyfill دقیقاً مثل نسخهٔ بومی نیست.
نکات کلیدی:
- ثبت اتریبیوت: ارثبری از Attr و بعد customAttributes.define() با یه اسم خطفاصلهدار
- کالبکها: attributeChangedCallback، connectedCallback، disconnectedCallback، connectedMoveCallback و adoptedCallback
- روی HTML، SVG، MathML و کاستوم المنتهای دیگه هم کار میکنه
- el.getAttributeNode() همون نمونهٔ کلاس رو برمیگردونه، پس با API المنت تداخل نداره
- واکنشها تو microtask بعدی اجرا میشن نه همزمان، و cloneNode() رجیستری رو منتقل نمیکنه




