Komponenty webowe: obalenie mitów i rzeczywiste możliwości
Komponenty webowe są często krytykowane za rzekomo ograniczoną możliwość przekazywania właściwości wyłącznie jako ciągi znaków przez atrybuty. To błędne przekonanie wynika z nieporozumienia dotyczącego mechanizmu attributeChangedCallback. Atrybuty HTML to statyczna część znaczników, niepowiązana bezpośrednio z runtime JavaScript. Aby przekazywać obiekty, tablice lub wartości prymitywne, należy używać getterów/setterów w klasie komponentu. Przeglądarka pozwala ustawiać właściwości dowolnego typu bezpośrednio przez DOM API lub proxy.
class MyElement extends HTMLElement {
set data(value) {
this._data = value;
this.render();
}
}
Shadow DOM zapewnia izolację stylów i DOM, co chroni przed konfliktami zewnętrznymi. Krytyka izolacji jako wady ignoruje wybór: Custom Elements działają bez Shadow DOM. Do personalizacji używaj zmiennych CSS i ::part():
my-component::part(button) {
background: var(--accent-color);
}
Mit duplikacji stylów: Adopted Style Sheets pozwalają stosować wspólne style do wszystkich instancji Shadow DOM.
Cykl życia zaczyna się w konstruktorze, a nie przy podłączeniu do DOM. Komponenty są tworzone w pamięci, manipulowane przez DocumentFragment do wirtualizacji bez renderowania.
Półprawda: rejestr i hooki cyklu życia
Globalny rejestr Custom Elements wymaga unikalnych nazw. Rozwiązanie to prefiksy (np. app-button) i try/catch przy rejestracji:
try {
customElements.define('app-button', ButtonElement);
} catch (e) {
console.warn('Konflikt nazw:', e);
}
Kolizje są wykrywane testami. Płaskie przestrzenie nazw to standardowy wzorzec w JS, DNS i HTML.
Hooki connectedCallback/disconnectedCallback uruchamiają się przy przenoszeniu w DOM. Naprawa to flaga inicjalizacji:
connectedCallback() {
if (this._initialized) return;
this._initialized = true;
this.init();
}
Wyrejestrowanie jest niemożliwe, ale to zaleta: przeglądarka buforuje konstruktor bez narzutu.
Rzeczywiste niuanse i rozwiązania
Parsowanie HTML wywołuje connectedCallback na otwierającym znaczniku przed przetworzeniem zawartości. DOM API są niedostępne. Użyj defer lub type="module" do opóźnionej inicjalizacji. Alternatywa to customElements.whenDefined():
const button = document.querySelector('app-button');
await customElements.whenDefined('app-button');
button.method();
Aby zagwarantować dostęp do potomków, zastosuj renderCallback lub podobne hooki.
Mocne strony komponentów webowych
Komponenty webowe łączą znaczniki HTML z JS natywnie. Niestandardowe tagi to markery do integracji na serwerze lub kliencie bez vendor lock-in.
Atomowe zarządzanie cyklem: przeglądarka powiadamia o podłączeniu/odłączeniu niezależnie od frameworka.
Podstawowy model dla Lit, Symbiote.js, mikro-frontendów. Działa w React, Vue, Angular, SPA, SSR.
- Izolacja bez narzutu: Shadow DOM jest opcjonalny.
- Natywna reaktywność: właściwości + proxy.
- Uniwersalność: od widżetów po pulpity z WebSocket i grafiką.
- Wirtualizacja: DocumentFragment dla list z 100k+ elementów.
- Stylizacja: CSS vars, ::part(), Adopted Style Sheets.
Co jest ważne
- Właściwości dowolnego typu przekazywane przez gettery/settery, atrybuty tylko dla ciągów znaków.
- Shadow DOM izoluje, ale można go wyłączyć w razie potrzeby; style przez vars i ::part.
- Globalny rejestr rozwiązany prefiksami i testami, kolizje rzadkie.
- Hooki
connected/disconnectedz flagą zapobiegają duplikacji inicjalizacji. - Asynchroniczność parsowania naprawiana przez defer/module lub whenDefined.
— Editorial Team
Brak komentarzy.