Linten van 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

Bouw stap voor stap een componentconfiguratie op, met Salesforce Lightning Web Components als uitgewerkt voorbeeld

Free Trial
Not for use with personal data

Salesforce Lightning Web Component (LWC)-sjablonen zijn HTML-bestanden gebouwd van aangepaste elementen: Salesforce-basisonderdelen zoals <lightning-button> en <lightning-icon>, en de componenten die je zelf maakt in de c- namespace, zoals <c-my-image>. Axe DevTools Linter controleert aangepaste elementen zodra je het vertelt wat die elementen renderen, met behulp van de global-components configuratieoptie.

Dit artikel bouwt een LWC-configuratie vanaf nul op. LWC is een goed uitgewerkt voorbeeld omdat het elk deel van de mappingsyntax gebruikt, inclusief componenten die geen eigen element renderen. De methode is toepasbaar op elke componentbibliotheek: beschrijf wat elke component rendert, verifieer die beschrijving met een testbestand en corrigeer vervolgens de mapping waar de twee niet overeenkomen.

Voor een introductie in het mappen van aangepaste componenten, zie Linten van aangepaste componenten. Voor de complete syntaxisreferentie, zie Configureren van Axe DevTools Linter.

Voordat je begint

Voeg een axe-linter.yml-bestand toe aan de root van je project. Elk voorbeeld hieronder komt in dat bestand. Als je de REST-endpoint in plaats van een editor-extensie gebruikt, gaat dezelfde configuratie in het config-object van het verzoek, zoals getoond in Linten van aangepaste componenten met de Axe DevTools Linter REST Endpoint.

Een mapping beschrijft wat de browser ontvangt

Dit is het idee dat elke andere beslissing eenvoudig maakt: een mapping beschrijft het element dat je component renderert, niet de tag die je in de sjabloon schrijft.

<lightning-button label="Save"> rendert een button waarvan de tekstinhoud "Opslaan" is. Geschreven als een mapping, is dat:

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

De speciale <text>-waarde geeft aan dat het label-attribuut de tekstinhoud van het element wordt, wat een knop zijn toegankelijke naam geeft. Met die mapping aanwezig, rapporteert Axe DevTools Linter een button-name-overtreding voor <lightning-button> gebruikt zonder label, precies zoals het zou doen voor een lege <button>.

Stap 1: Map de componenten die een element renderen

Begin met componenten die moeiteloos op één natief element projecteren en map alleen de attributen die toegankelijkheidsinformatie bevatten.

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

Componentnamen zijn hoofdlettergevoelig en komen overeen met de tag zoals je deze in de sjabloon schrijft, dus LWC's kebab-gevalnamen worden ongewijzigd gebruikt.

Voor de andere speciale waarden (aria-* om ARIA-attributen door te geven, <element> om een attribuut het uit te zenden element te laten kiezen, en default om een waarde te declareren die de component altijd renderert), zie de walkthrough in Linten van aangepaste componenten met de Axe Accessibility Linter-extensie voor VS Code of de JetBrains-plugin.

Stap 2: Verklaar de wrappers die niets renderen

LWC gebruikt <template> voor het wortelelement van een component en opnieuw voor iteratie en conditionele instructies:

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

In HTML zijn de inhoud van een <template>-element inert: de browser rendert ze niet, en assis-tieve technologie kan deze niet bereiken. Axe DevTools Linter evalueert de markup die een gebruiker daadwerkelijk krijgt, dus het rapporteert geen inhoud binnen een <template>. LWC gebruikt dezelfde tagnaam voor een compile-tijdinstructie die helemaal geen element produceert, dus moet de linter worden verteld wat deze wrappers worden. De bovenstaande markup bereikt de browser als volgt:

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

Het verklaren van template in je configuratie is wat de linter in staat stelt door die wrappers heen te kijken naar de markup binnenin. Omdat een mapping een element moet benoemen, en een mapping overal van toepassing is waar de tag verschijnt, is het element dat je kiest van belang. Twee keuzes doorwerken met de bovenstaande lijst laat zien waarom.

Een generieke container proberen

Een div is de natuurlijke eerste gok, aangezien een wrapper klinkt als een generieke container:

global-components:
  template: div

Axe DevTools Linter evalueert nu de lijst alsof je de <template> als een div had geschreven:

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

En het rapporteert een overtreding op de <ul>-regel:

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

Het rapport is correct over de markup die het heeft gekregen, maar die markup is niet wat de browser ontvangt. LWC verwijdert de wrapper, dus de weergegeven lijst bevat direct lijst-items en is perfect geldig. De overtreding komt voort uit het vervangende element, niet uit je sjabloon.

De weergegeven relatie matchen

Map nu template naar het element dat de browser daadwerkelijk binnen de lijst vindt:

global-components:
  template: li

De linter evalueert dezelfde lijst als volgt:

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

Er wordt geen list-overtreding gerapporteerd, omdat de <ul> direct een li bevat, wat een van de elementen is die het regelbericht hierboven toestaat, en het is ook de relatie die de browser krijgt. De verdubbelde li bestaat alleen in de belemmerde weergave van je bestand: hij staat in voor een wrapper die niets rendert, en je schrijft hem nooit in een sjabloon.

note

template uit je configuratie weglaten vermijdt ook de overtreding, maar dan wordt er helemaal niets binnenin je sjablonen geëvalueerd, wat het probleem is dat Stap 2 wilde oplossen.

Beide keuzes controleren de inhoud binnenin

Het vervangende element beïnvloedt alleen hoe de wrapper zelf aan de linter verschijnt. De markup binnenin wordt in beide gevallen geëvalueerd. Voeg een afbeelding zonder alternatieve tekst toe aan dezelfde lijst:

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

Zowel template: div als template: li rapporteren de ontbrekende alternatieve tekst op de afbeelding:

image-alt: Images must have alternative text

Met template: div krijg je dat resultaat plus de onterecht gemelde list overtreding, wat het praktische verschil is tussen de twee. Omdat het itereren van lijst-items het meest voorkomende gebruik van <template> is, komt het mappen naar li het vaakst overeen met de gerenderde uitvoer, en dat is het aanbevolen startpunt.

note

Drie regels controleren of een container het juiste soort direct kind bevat: list voor <ul> en <ol>, definition-list voor <dl>, en summary-name voor <details>. Waar een <template> direct binnen een van die vier containers zit, neemt je vervangende element zijn plaats in, dus melden deze drie regels mogelijk niet wat ze zouden doen voor het gelijkwaardige gewone HTML. Geen enkele andere regel wordt beïnvloed en de inhoud binnen de sjabloon wordt nog steeds volledig gecontroleerd.

Stap 3: Verifieer je configuratie

Ga er niet van uit dat een mapping zich gedraagt zoals je bedoeld hebt. De meest betrouwbare controle is om dezelfde markup twee keer te schrijven, één keer met je componenten en één keer als de gewone HTML die je verwacht dat ze renderen, en te bevestigen dat beide dezelfde resultaten opleveren.

Maak een klein testbestand, scratch.html, waar dan ook in het project dat Axe DevTools Linter controleert:

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

Maak vervolgens zijn gewone HTML-tweeling, scratch-expected.html, die de markup bevat waarvan je verwacht dat die componenten renderen:

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

Met de mappings uit Stappen 1 en 2 in plaats, rapporteren beide bestanden dezelfde twee overtredingen: image-alt voor de afbeelding zonder alternatieve tekst, en button-name voor de knop zonder toegankelijke naam. Overeenkomende resultaten betekenen dat de mappings je componenten correct beschrijven. Een overtreding in één bestand maar niet in het andere wijst op de configuratie in plaats van op je markup.

Dit paar toont ook waarom deze controle de moeite waard is. Zonder de template-mapping van Stap 2, rapporteert scratch.html helemaal niets terwijl scratch-expected.html beide overtredingen rapporteert, en dat verschil is het signaal dat er iets in de configuratie ontbreekt.

Er zijn drie handige manieren om de resultaten te zien:

Door de componentnaam aan elk resultaat toe te voegen, wordt het veel gemakkelijker om grotere configuraties te debuggen, omdat het laat zien welke mapping een overtreding heeft veroorzaakt. Zie Analyseren van op maat gemaakte component-overtredingen.

Bepalen wat een mapping moet vereisen

Sommige componenten renderen verschillende markup afhankelijk van hoe ze worden gebruikt, en het in kaart brengen ervan is een beleidsbeslissing in plaats van een eenvoudige vertaling. <lightning-icon> is een goed voorbeeld: een pictogram zonder alternative-text is decoratief, terwijl een pictogram met alternative-text betekenis overbrengt.

Het koppelen van <lightning-icon> aan img betekent dat de linter elk pictogram vraagt om zijn alternatieve tekst te verklaren. Een expliciet lege waarde voldoet aan dat verzoek:

<!-- 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>

Dat is een nuttige conventie, omdat het de bedoeling van elk pictogram zichtbaar maakt in de template in plaats van stilzwijgend weggelaten. Als je het liever niet aanneemt, laat <lightning-icon> dan uit je configuratie en de linter zal het niet evalueren.

When a component always renders the same value for an attribute, such as a fixed role, use default to record that value. A default takes effect only when the value is not empty, and a default can set an attribute but cannot supply <text> content. See Standaardattributen.

important

Map only the attributes that carry accessibility information, and confirm what each component renders before mapping it. The examples in this article follow the markup the Salesforce base components produce, but your own components, and any component you wrap, need the same check.

Map alleen de attributen die toegankelijkheidsinformatie bevatten, en bevestig wat elke component rendert voordat je deze in kaart brengt. De voorbeelden in dit artikel volgen de markup die de basiscomponenten van Salesforce produceren, maar je eigen componenten, en elke component die je omwikkelt, hebben dezelfde controle nodig.

Toepassing op je eigen componenten

  1. De bovenstaande stappen generaliseren naar elke componentbibliotheek:, such as buttons, links, images, form controls, and headings. Those give you the most value for the least configuration.
  2. For each one, note what it renders and which attributes carry accessibility information, then map only those attributes.
  3. Declare wrappers that render nothing of their own, choosing a substitute element that preserves the relationship the browser sees.
  4. Verify each mapping against its plain-HTML equivalent before relying on it.
  5. Revisit the configuration when your components change. A mapping only reflects how a component behaved on the day the mapping was written.

If your library is one of the libraries Axe DevTools Linter already knows about, you can skip most of this work. See Preconfigured Component Libraries.

See Also