Gli elementi personalizzati ti consentono di creare tag HTML personalizzati. Questo elenco di controllo illustra le best practice per aiutarti a creare elementi di alta qualità.
Gli elementi personalizzati ti consentono di estendere l'HTML e definire i tuoi tag. È un
funzione incredibilmente potente, ma sono anche di basso livello, il che significa che
sempre chiaro il modo migliore per implementare il proprio elemento.
Per aiutarti a creare le migliori esperienze possibili, abbiamo creato questa presentazione
elenco di controllo. Suddivide tutte le cose che pensiamo siano necessarie per
un elemento personalizzato ben gestito.
Elenco di controllo
DOM shadow
Crea una radice ombra per incapsulare gli stili.
Why?
L'incapsulamento degli stili nella radice ombra dell'elemento ne garantisce il funzionamento
a prescindere da dove viene utilizzata. Ciò è particolarmente importante se uno sviluppatore
vuole posizionare l'elemento all'interno della radice ombra di un altro elemento. Questo
vale anche per elementi semplici come una casella di controllo o un pulsante di opzione. Potrebbe essere
del caso che gli unici contenuti all'interno della radice ombra siano gli stili
le istanze server autonomamente.
Il costruttore è quando hai una consapevolezza esclusiva dell'elemento.
È il momento giusto per impostare dettagli di implementazione che non vuoi che altri
a aggirarle. Questa operazione verrà eseguita in una richiamata successiva, ad esempio
connectedCallback, dovrai proteggerti
situazioni in cui l'elemento viene scollegato e poi ricollegato al documento.
Posiziona gli eventuali elementi secondari creati dall'elemento nella sua radice ombra.
Why?
I componenti secondari creati dall'elemento fanno parte della sua implementazione e devono essere
privato. Senza la protezione di una radice shadow, JavaScript esterno potrebbe
interferire inavvertitamente con questi bambini.
Usa <slot> per proiettare i bambini DOM di luce nel tuo DOM ombra
Why?
Consenti agli utenti del tuo componente di specificare i contenuti al suo interno, poiché HTML secondario rende il tuo componente più componibile. Quando un browser non supporta gli elementi personalizzati, i contenuti nidificati rimangono disponibili, visibili e accessibili.
Imposta uno stile di visualizzazione :host (ad es. block,
inline-block, flex) a meno che tu non preferisca il valore predefinito di
inline.
Why?
Gli elementi personalizzati sono display: inline per impostazione predefinita, quindi l'impostazione della loro
width o height non avranno alcun effetto. Questo spesso
è una sorpresa per gli sviluppatori e potrebbe causare problemi relativi a:
il layout della pagina. A meno che tu non preferisca un display inline,
deve sempre impostare un valore predefinito per display.
Aggiungi uno stile di visualizzazione :host che rispetti l'attributo nascosto.
Why?
Un elemento personalizzato con uno stile display predefinito, ad esempio
:host { display: block }, sostituirà la specificità inferiore
integrato
.
hidden.
Questo potrebbe sorprenderti se prevedi di impostare hidden
dell'elemento per eseguirne il rendering display: none. Inoltre,
a uno stile display predefinito, aggiungi il supporto per hidden
con :host([hidden]) { display: none }.
Non sostituire gli attributi globali impostati dall'autore.
Why?
Gli attributi globali sono quelli presenti in tutti gli elementi HTML. Alcune
esempi includono tabindex e role. Un elemento personalizzato
potresti voler impostare il valore iniziale di tabindex su 0 in modo che corrisponda alla tastiera
attivabile. Tuttavia, devi sempre verificare prima se lo sviluppatore che utilizza
l'elemento lo ha impostato su un altro valore. Ad esempio, se hanno impostato
tabindex a -1, è un indicatore che non vogliono che
per essere interattivo.
Accetta sempre i dati primitivi (stringhe, numeri, booleani) come attributi
o proprietà.
Why?
Gli elementi personalizzati, come le controparti integrate, devono essere configurabili.
La configurazione può essere trasmessa in modo dichiarativo, tramite attributi o
tramite le proprietà JavaScript. Idealmente ogni attributo dovrebbe essere collegato
una proprietà corrispondente.
Cerca di mantenere sincronizzati gli attributi e le proprietà dei dati primitivi, rispecchiando le
da attribuire e viceversa.
Why?
Non puoi mai sapere come un utente interagirà con il tuo elemento. Potrebbero
impostare una proprietà in JavaScript e aspettarsi di leggerlo
utilizzando un'API come getAttribute(). Se ogni attributo ha un valore
una proprietà corrispondente ed entrambe riflettono la,
agli utenti di lavorare con il tuo elemento. In altre parole, la chiamata
setAttribute('foo', value) deve anche impostare un valore
foo e viceversa. Esistono, naturalmente, delle eccezioni
questa regola. Non devi riflettere le proprietà dell'alta frequenza, ad esempio
currentTime in un video player. Usa il tuo buon senso. Se
sembra che un utente interagisca con una proprietà o un attributo
non è oneroso rifletterle, allora fallo.
Cerca di accettare solo dati avanzati (oggetti, array) come proprietà.
Why?
In generale, non esistono esempi di elementi HTML integrati che
accettare dati avanzati (matrici e oggetti JavaScript semplici) tramite
attributi. Le informazioni aggiuntive vengono invece accettate tramite chiamate al metodo
proprietà. Ci sono un paio di svantaggi evidenti nell'accettare informazioni aggiuntive come
attributi: può essere costoso serializzare un oggetto di grandi dimensioni in una stringa e
tutti i riferimenti agli oggetti andranno persi nel processo di stringificazione. Per
ad esempio, se crei una stringa per un oggetto che ha un riferimento a un altro oggetto,
o magari un nodo DOM, questi riferimenti andranno persi.
Non riflettere le proprietà dei dati approfonditi negli attributi.
Why?
Riflettere le proprietà dei dati dettagliati agli attributi è inutilmente costoso,
che richiedono la serializzazione e la deserializzazione degli stessi oggetti JavaScript. A meno che
caso d'uso che può essere risolto solo con questa funzione, probabilmente
è meglio evitarlo.
Ti consigliamo di controllare le proprietà che potrebbero essere state impostate prima dell'elemento
con upgrade eseguito.
Why?
Uno sviluppatore che utilizza il tuo elemento potrebbe tentare di impostare una proprietà sull'elemento
prima che venga caricata la relativa definizione. Ciò è particolarmente vero se
che lo sviluppatore utilizza un framework per gestire i componenti di caricamento, assegnando loro un'etichetta
alla pagina e associare le relative proprietà a un modello.
Per gli elementi che devono esprimere il proprio stato occorre utilizzare gli attributi. La
Generalmente l'attributo class è considerato di proprietà del
sviluppatore di usare l'elemento e di scriverci personalmente potrebbe inavvertitamente
calpesta le classi degli sviluppatori.
Eventi
Eventi di invio in risposta all'attività dei componenti interni.
Why?
Il componente può avere proprietà che cambiano in risposta a un'attività che
solo il tuo componente sa, ad esempio, se un timer o un'animazione
o il caricamento di una risorsa. È utile inviare eventi
in risposta a queste modifiche per notificare all'host che lo stato del componente
diverso.
Non inviare eventi in risposta all'impostazione di una proprietà da parte dell'host (verso il basso
flusso di dati).
Why?
Inviare un evento in risposta all'impostazione di una proprietà da parte dell'host è superfluo
(l'host conosce lo stato attuale perché lo ha appena impostato). Eventi di dispacciamento
in risposta a un'impostazione dell'host, una proprietà può causare loop infiniti con dati
sistemi di associazione.
È possibile che uno sviluppatore che utilizza il tuo elemento voglia eseguire l'override di
allo stato iniziale. Ad esempio, la modifica dell'ARIA role o della regolabilità con
tabindex. Controlla se questi e altri attributi globali sono stati impostati,
prima di applicare i tuoi valori.
Uno sviluppatore potrebbe tentare di impostare una proprietà sull'elemento prima che
la definizione è stata caricata. Ciò è particolarmente vero se lo sviluppatore utilizza una
che gestisce il caricamento dei componenti, inserendoli nella pagina
associando le proprie proprietà a un modello.
Nell'esempio seguente, Angular sta associando in modo dichiarativo il valore
isChecked alla proprietà checked della casella di controllo. Se la definizione di
la casella di controllo "howto" è stata caricata tramite caricamento lento. È possibile che Angular provi a impostare
la proprietà selezionata prima dell'upgrade dell'elemento.
Un elemento personalizzato dovrebbe gestire questo scenario controllando se alcune proprietà hanno
è già stato impostato sulla sua istanza. La <howto-checkbox>
dimostra questo pattern utilizzando un metodo chiamato _upgradeProperty().
_upgradeProperty() acquisisce il valore dell'istanza di cui non è stato eseguito l'upgrade ed elimina
la proprietà in modo che non esegua lo shadowing del setter delle proprietà dell'elemento personalizzato.
In questo modo, quando la definizione dell'elemento viene caricata, può immediatamente
che riflettano lo stato corretto.
Evita problemi di rientro
Si può avere la tentazione di usare attributeChangedCallback() per riflettere lo stato in una
proprietà sottostante, ad esempio:
// When the [checked] attribute changes, set the checked property to match.attributeChangedCallback(name,oldValue,newValue){if(name==='checked')this.checked=newValue;}
Questo può creare un ciclo infinito se il setter delle proprietà riflette anche
l'attributo.
setchecked(value){constisChecked=Boolean(value);if(isChecked)// OOPS! This will cause an infinite loop because it triggers the// attributeChangedCallback() which then sets this property again.this.setAttribute('checked','');elsethis.removeAttribute('checked');}
Un'alternativa è consentire al setter della proprietà di riflettere sull'attributo e
fare in modo che il getter determini il proprio valore in base all'attributo.
In questo esempio, l'aggiunta o la rimozione dell'attributo stabilirà anche la proprietà.
Infine, puoi usare attributeChangedCallback() per gestire gli effetti collaterali
come l'applicazione degli stati ARIA.
attributeChangedCallback(name,oldValue,newValue){consthasValue=newValue!==null;switch(name){case'checked':// Note the attributeChangedCallback is only handling the *side effects*// of setting the attribute.this.setAttribute('aria-checked',hasValue);break;...}}
[[["Facile da capire","easyToUnderstand","thumb-up"],["Il problema è stato risolto","solvedMyProblem","thumb-up"],["Altra","otherUp","thumb-up"]],[["Mancano le informazioni di cui ho bisogno","missingTheInformationINeed","thumb-down"],["Troppo complicato/troppi passaggi","tooComplicatedTooManySteps","thumb-down"],["Obsoleti","outOfDate","thumb-down"],["Problema di traduzione","translationIssue","thumb-down"],["Problema relativo a esempi/codice","samplesCodeIssue","thumb-down"],["Altra","otherDown","thumb-down"]],["Ultimo aggiornamento 2017-08-14 UTC."],[],[]]