Tag: web-components, custom-elements, shadow-dom, html-templates, frontend, javascript, browser-apis
Livello: intermedio
TL;DR: Standard W3C per creare componenti UI incapsulati e riutilizzabili nativamente nel browser, indipendenti da framework esterni, basati su Custom Elements, Shadow DOM e HTML Templates.
Tre standard cardine: Custom Elements, Shadow DOM e HTML Template/Slot.
I Custom Elements richiedono un trattino nel nome (kebab-case) per evitare conflitti futuri con tag HTML nativi.
Shadow DOM isola stili CSS e albero DOM, impedendo leak di stile verso l'esterno o dall'esterno.
Modalità Shadow DOM: open permette accesso via element.shadowRoot, closed nega l'accesso programmatico dall'esterno.
Ciclo di vita: connectedCallback viene invocato quando il componente entra nel DOM del documento.
disconnectedCallback viene eseguito alla rimozione dal DOM per cleanup di timer e listener.
attributeChangedCallback intercetta le modifiche solo per gli attributi dichiarati nel getter statico observedAttributes.
I tag <template> e <slot> consentono markup inerte riutilizzabile e proiezione di nodi dal Light DOM.
:host applica regole di stile all'elemento custom stesso dall'interno dello Shadow DOM.
::slotted() seleziona e stilizza nodi proiettati tramite slot, limitandosi al nodo radice distribuito.
Q: Qual è la differenza architetturale principale tra Web Components e componenti React?
R: I Web Components sono standard nativi del browser basati su incapsulamento reale via Shadow DOM, mentre React usa astrazioni proprietarie su Virtual DOM.
Q: Perché il nome di un Custom Element deve contenere sempre un trattino?
R: È una regola dello standard W3C per garantire retrocompatibilità ed evitare collisioni di naming con futuri tag HTML nativi.
Q: A cosa serve il getter statico observedAttributes?
R: Specifica al browser la lista esatta di attributi da monitorare per innescare l'esecuzione di attributeChangedCallback.
Dimenticare la chiamata a super() nel costruttore prima di accedere a this.
Manipolare il DOM o impostare attributi nel constructor anziché all'interno di connectedCallback.
Omettere un attributo da observedAttributes, con conseguente mancata esecuzione del listener di mutazione.
Mancata rimozione degli event listener globali nel disconnectedCallback, causando memory leak.
Tentare di sovrascrivere stili dello Shadow DOM con CSS globale standard senza usare Custom CSS Properties.
```class UserCard extends HTMLElement {
static get observedAttributes() {
return ['name'];
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.render();
}
attributeChangedCallback(name: string, oldValue: string, newValue: string) {
if (oldValue !== newValue) {
this.render();
}
}
disconnectedCallback() {
// Cleanup listeners
}
private render() {
if (!this.shadowRoot) return;
const name = this.getAttribute('name') ?? 'Guest';
this.shadowRoot.innerHTML = `
<style>
:host { display: block; border: 1px solid #ccc; padding: 8px; }
span { font-weight: bold; }
</style>
<span>Utente:</span> ${name}
<slot></slot>
`;
}
}
customElements.define('user-card', UserCard);
```
[ ] Meccanismo di penetrazione CSS con CSS Custom Properties e shadow parts (::part)
[ ] Differenze di accessibilità e focus delegation con delegatesFocus nel Shadow DOM
[x] Ciclo di vita dei Custom Elements e registrazione tramite customElements.define
[x] Proiezione di contenuti con Named Slot e Fallback Content