From my notes

Best practices

Questions and flashcards from your notes on the Vue docs' Best Practices chapter — shallow reactivity for large data, v-once, v-memo, lazy components and virtual scrolling, focus after route changes, heading levels, landmarks and their roles, aria-hidden, labels and descriptions, the aria-labelledby spelling, URL injection and safe rich text — with a fact check of the notes.

Written from your performance, accessibility and security note. The matching study page is Best practices — deployment, performance, accessibility, security.

Know

  • Performance: shallowRef for large replaced data, v-once, v-memo for big lists, defineAsyncComponent, virtual scrolling.
  • Accessibility: focus after client-side navigation, heading order, landmark roles, aria-hidden on focusable elements, an accessible password field, aria-labelledby.
  • Security: what Vue escapes, javascript: URLs, and rendering user rich text safely.

Fact check of your notes

Gotcha· The lazy-loading API is defineAsyncComponent

loadAsyncComponent does not exist; it is defineAsyncComponent, or the Lazy prefix in Nuxt.

Gotcha· Do not skip heading levels going down

"Never skip headings h4 to h2" is the allowed direction. The rule is not to jump down more than one level, such as from h2 to h4. Going back up from h4 to h2 is fine.

Gotcha· Landmarks map to roles, not labels

<main>, <nav>, <header> and <footer> map to ARIA landmark roles (main, navigation, banner, contentinfo). A label is the name you add with aria-label when there are several landmarks of one kind.

Gotcha· aria-labelledby has a double l

The heading says aria-labeledby; the attribute is aria-labelledby, and the misspelled one is silently ignored. Your code example has it right.

Exercise

Exercise
  • Render 10,000 rows, profile scrolling, then virtualize the list and profile again.
  • Navigate an SPA with a screen reader (VoiceOver: Cmd+F5) before and after adding a skip link that receives focus on route change.
  • Try a javascript:alert(1) URL in a :href binding, then add a check that only allows http, https and mailto.

Be able to say

Be able to say· How do you keep a Vue app fast when it grows?

"Two kinds of cost. Page load: split code at routes and with defineAsyncComponent for heavy components, so users only download what they use. Updates: avoid deep reactivity on big data that is replaced rather than mutated (shallowRef), keep computeds stable, skip static subtrees with v-once and large-list re-renders with v-memo, and virtualize long lists so the number of DOM nodes stays small. I measure with the browser's performance panel and Vue DevTools first, then apply the one that fits."

Be able to say· What accessibility work does a Vue SPA need beyond semantic HTML?

"Route changes do not load a new page, so I move focus to a skip link or the main heading on each navigation. I keep heading levels in order, use landmark elements, label every control with a real <label> or aria-label, link hints and errors with aria-describedby, hide decorative icons with aria-hidden but never on something focusable, and avoid placeholders as labels because they disappear and usually fail contrast. Then I test with a keyboard and a screen reader."

Be able to say· Does Vue protect you from XSS?

"Partly. Text interpolation and attribute bindings are escaped, so user text cannot become markup. But v-html renders whatever it gets, a bound href can still be a javascript: URL, style bindings can carry user CSS, and compiling templates from user input runs code. So user rich text goes through a sanitizer or a Markdown renderer without raw HTML, URLs are checked, and a Content Security Policy is the second line of defence."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on this page and the section overview.