Linting di Salesforce Lightning Web Components (LWC)

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard

Costruisci una configurazione del componente passo dopo passo, utilizzando Salesforce Lightning Web Components come esempio pratico

Free Trial
Not for use with personal data

I modelli di componente di Salesforce Lightning Web (LWC) sono file HTML costruiti da elementi personalizzati: componenti base di Salesforce come <lightning-button> e <lightning-icon>, e i componenti che crei tu stesso nel namespace c-, come <c-my-image>. Axe DevTools Linter verifica gli elementi personalizzati una volta che gli dici cosa rendono questi elementi, utilizzando l'opzione di configurazione global-components.

Questo articolo costruisce una configurazione LWC da zero. LWC è un buon esempio pratico perché mette alla prova ogni parte della sintassi di mapping, inclusi i componenti che non rendono alcun elemento proprio. Il metodo si applica a qualsiasi libreria di componenti: descrivi cosa rende ogni componente, verifica quella descrizione rispetto a un file di test, quindi correggi il mapping quando i due non corrispondono.

Per un'introduzione al mapping di componenti personalizzati, vedi Linting di Componenti Personalizzati. Per la sintassi completa, vedi Configurazione di Axe DevTools Linter.

Prima di Iniziare

Aggiungi un file axe-linter.yml alla radice del tuo progetto. Ogni esempio sottostante si trova in quel file. Se utilizzi l'endpoint REST invece di un'estensione dell'editor, la stessa configurazione va nell'oggetto config della richiesta, come mostrato in Linting di Componenti Personalizzati con l'Endpoint REST di Axe DevTools Linter.

Un Mapping Descrive Cosa Riceve il Browser

Questa è l'idea che rende ogni altra decisione semplice: un mapping descrive l'elemento che il tuo componente rende, non il tag che scrivi nel modello.

<lightning-button label="Save"> rende un button il cui contenuto testuale è "Salva". Scritto come mapping, è:

global-components:
  lightning-button:
    element: button
    attributes:
      - label: <text>

Il valore speciale <text> indica che l'attributo label diventa il contenuto testuale dell'elemento, che è ciò che dà a un pulsante il suo nome accessibile. Con quel mapping in atto, Axe DevTools Linter segnala una violazione button-name per <lightning-button> usato senza label, esattamente come farebbe per un <button> vuoto.

Passo 1: Mappa i Componenti Che Rendono un Elemento

Inizia con i componenti che mappano chiaramente su un singolo elemento nativo, e mappa solo gli attributi che contengono informazioni di accessibilità.

global-components:
  # Salesforce base components
  lightning-button:
    element: button
    attributes:
      - label: <text>
  lightning-icon:
    element: img
    attributes:
      - alternative-text: alt
  # Components you author yourself
  c-my-image:
    element: img
    attributes:
      - alternative-text: alt

I nomi dei componenti sono sensibili alle maiuscole e corrispondono al tag come lo scrivi nel modello, quindi i nomi in kebab-case di LWC vengono usati così come sono.

Per gli altri valori speciali (aria-* per far passare gli attributi ARIA, <element> per permettere a un attributo di scegliere l'elemento emesso, e default per dichiarare un valore che il componente rende sempre) vedi la guida in Linting di Componenti Personalizzati con l'Estensione Axe Accessibility Linter per VS Code o il Plugin JetBrains.

Passo 2: Dichiara i Wrapper Che Non Rendono Nulla

LWC usa <template> per l'elemento radice di un componente e di nuovo per iterazioni e condizionali:

<template>
  <ul>
    <template for:each={items} for:item="item">
      <li key={item.id}>{item.name}</li>
    </template>
  </ul>
</template>

In HTML, i contenuti di un elemento <template> sono inerti: il browser non li rende e la tecnologia assistiva non può accedervi. Axe DevTools Linter valuta il markup che l'utente effettivamente riceve, quindi non segnala il contenuto all'interno di un <template>. LWC utilizza lo stesso nome di tag per un'istruzione a tempo di compilazione che non produce alcun elemento, quindi il linter deve essere informato su cosa diventano questi wrapper. Il markup sopra raggiunge il browser in questo modo:

<ul>
  <li></li>
  <li></li>
</ul>

Dichiarare template nella tua configurazione è ciò che permette al linter di vedere attraverso quei wrapper al markup interno. Poiché un mapping deve nominare un elemento e un mapping si applica ovunque il tag appaia, l'elemento che scegli è importante. Esaminare due scelte con l'elenco sopra mostra perché.

Provare un Contenitore Generico

Un div è la prima ipotesi naturale, poiché un wrapper sembra un contenitore generico:

global-components:
  template: div

Axe DevTools Linter ora valuta l'elenco come se avessi scritto il <template> come un div:

<ul>
  <div>
    <li></li>
  </div>
</ul>

E segnala una violazione sulla linea <ul>:

list: <ul> and <ol> must only directly contain <li>, <script> or <template> elements

Il rapporto è corretto riguardo al markup fornito, ma quel markup non è ciò che il browser riceve. LWC rimuove il wrapper, quindi l'elenco reso contiene voci di elenco direttamente ed è perfettamente valido. La violazione proviene dall'elemento sostituto, non dal tuo modello.

Corrispondenza della Relazione Rappresentata

Ora mappa template all'elemento che il browser effettivamente trova all'interno dell'elenco:

global-components:
  template: li

Il linter valuta lo stesso elenco in questo modo:

<ul>
  <li>
    <li></li>
  </li>
</ul>

Non viene segnalata alcuna violazione list, perché il <ul> contiene direttamente un li, che è uno degli elementi consentiti nel messaggio di regole sopra e rispecchia la relazione che il browser ottiene. Il doppio li esiste solo nella vista del linter del tuo file: rappresenta un wrapper che non rende nulla, e non lo scriverai mai in un modello.

note

Lasciare template fuori dalla tua configurazione evita anche la violazione, ma in tal caso nulla all'interno dei tuoi modelli viene valutato, che è il problema che il Passo 2 mirava a risolvere.

Entrambe le Scelte Controllano il Contenuto Interno

L'elemento sostituto influisce solo su come il wrapper stesso appare al linter. Il markup interno viene valutato in entrambi i modi. Aggiungi un'immagine senza testo alternativo allo stesso elenco:

<template>
  <ul>
    <template for:each={items} for:item="item">
      <li key={item.id}><img src={item.url}></li>
    </template>
  </ul>
</template>

Sia template: div che template: li segnalano la mancanza di testo alternativo sull'immagine:

image-alt: Images must have alternative text

Con template: div ottieni quel risultato più la violazione spurie list, che è la differenza pratica tra i due. Poiché l'iterazione delle voci di elenco è l'uso più comune di <template>, mapparlo su li corrisponde più spesso al risultato reso, ed è il punto di partenza raccomandato.

note

Tre regole verificano che un contenitore contenga il giusto tipo di figlio diretto: list per <ul> e <ol>, definition-list per <dl>, e summary-name per <details>. Dove un <template> si trova direttamente dentro uno di quei quattro contenitori, il tuo elemento sostituto prende il suo posto, quindi queste tre regole potrebbero non riportare ciò che farebbero per l'HTML semplice equivalente. Nessun'altra regola è influenzata, e il contenuto all'interno del modello viene comunque verificato completamente.

Passo 3: Verifica la Tua Configurazione

Non supporre che un mapping si comporti come previsto. Il controllo più affidabile è scrivere lo stesso markup due volte, una volta con i tuoi componenti e una volta come l'HTML semplice che ti aspetti che rendano, e confermare che entrambi producano gli stessi risultati.

Crea un piccolo file di test, scratch.html, da qualsiasi parte nel progetto che Axe DevTools Linter verifica:

<template>
  <c-my-image src="cat.jpg"></c-my-image>
  <lightning-button></lightning-button>
</template>

Quindi crea il suo gemello in HTML semplice, scratch-expected.html, contenente il markup che ti aspetti che quei componenti rendano:

<img src="cat.jpg">
<button></button>

Con i mapping dei Passi 1 e 2 in atto, entrambi i file segnalano le stesse due violazioni: image-alt per l'immagine senza testo alternativo, e button-name per il pulsante senza nome accessibile. Risultati corrispondenti significano che i mapping descrivono correttamente i tuoi componenti. Una violazione in un file ma non nell'altro indica la configurazione piuttosto che il tuo markup.

Questa coppia mostra anche perché vale la pena fare il controllo. Senza il mapping template del Passo 2, scratch.html non segnala nulla mentre scratch-expected.html segnala entrambe le violazioni, e quella discrepanza è il segnale che manca qualcosa nella configurazione.

Ci sono tre modi convenienti per vedere i risultati:

Aggiungere il nome del componente a ciascun risultato rende le configurazioni più grandi molto più facili da debug, perché mostra quale mappatura ha prodotto una violazione. Vedi Analizzare le violazioni dei componenti personalizzati.

Decidere cosa dovrebbe richiedere una mappatura

Alcuni componenti generano un markup diverso a seconda di come vengono usati, e mappare tali componenti è una decisione politica piuttosto che una semplice traduzione. <lightning-icon> è un buon esempio: un'icona senza alternative-text è decorativa, mentre un'icona con alternative-text trasmette un significato.

Mappare <lightning-icon> su img significa che il linter chiederà ad ogni icona di dichiarare il suo testo alternativo. Un valore esplicitamente vuoto soddisfa tale richiesta:

<!-- Reported: an image with no alternative text -->
<lightning-icon icon-name="utility:check"></lightning-icon>

<!-- Not reported: explicitly decorative -->
<lightning-icon icon-name="utility:check" alternative-text=""></lightning-icon>

È una convenzione utile, perché rende visibile l'intento di ciascuna icona nel modello anziché implicito per omissione. Se preferisci non adottarla, lascia <lightning-icon> fuori dalla tua configurazione e il linter non lo valuterà.

Quando un componente genera sempre lo stesso valore per un attributo, come un role fisso, utilizza default per registrare quel valore. Un default è efficace solo quando il valore non è vuoto, e un default può impostare un attributo ma non fornire contenuti <text>. Vedi Attributi predefiniti.

important

Mappa solo gli attributi che contengono informazioni sull'accessibilità e verifica cosa genera ciascun componente prima di mapparlo. Gli esempi in questo articolo seguono il markup che i componenti base di Salesforce producono, ma i tuoi componenti e qualsiasi componente tu avvolga necessitano dello stesso controllo.

Applicare questo ai tuoi componenti

I passaggi sopra si generalizzano a qualsiasi libreria di componenti:

  1. Elenca i componenti che generano un elemento interattivo o significativo, come bottoni, collegamenti, immagini, controlli di modulo e intestazioni. Questi forniscono il massimo valore con la minima configurazione.
  2. Per ciascuno di essi, nota cosa genera e quale attributo contiene informazioni sull'accessibilità, quindi mappa solo quegli attributi.
  3. Dichiara i wrapper che non generano nulla di proprio, scegliendo un elemento sostitutivo che preserva la relazione che il browser vede.
  4. Verifica ciascuna mappatura rispetto al suo equivalente HTML puro prima di fare affidamento su di essa.
  5. Rivedi la configurazione quando i tuoi componenti cambiano. Una mappatura riflette solo come si è comportato un componente nel giorno in cui è stata scritta.

Se la tua libreria è una delle librerie che Axe DevTools Linter già conosce, puoi saltare la maggior parte di questo lavoro. Vedi Librerie di componenti preconfigurate.

Vedi anche