Best practices proven by the quasar 2.33.1 shipped docs
Each item cites the page inside dist/mcp/ (of the installed package).
Performance
- Prefer the responsive CSS classes (
gt-sm,lt-md,lt-xl, visibility classes) over reading$q.screenin JavaScript when you can; the docs recommend it for performance (options/screen-plugin.md:4). - Large
QTree: two remedies in increasing order of effect (vue-components/tree.md:214-228):no-transition— drops the expand/collapse animation and lets collapsed subtrees leave the DOM.virtual-scroll(v2.25+) — constant cost regardless of expansion; give the tree a height or pointvirtual-scroll-targetat a scrolling ancestor.
QSelectvirtual scroll: freeze theoptionsarray and referenceoption-value/option-labelfunctions from scope instead of inline arrow functions (API desc,dist/api/QSelect.json).lazy-rules: 'ondemand'defersQInput/QSelectvalidation to form submit or a manualvalidate()call when the default blur timing fights you.
Dialog plugin
- Custom components invoked through
$q.dialog({ component: ... })must bootstrap withuseDialogPluginComponent()(vue-composables/use-dialog-plugin-component.md). - Since v2.28 the composable forwards the dismissal reason
(
cancel,backdrop,escape,programmatic) toonCancel/onDismiss: bind@hide="onDialogHide"directly — a wrapper like@hide="onDialogHide()"drops the event — and settle cancel throughonDialogCancel(), nothide().
State, timers, platform
useQuasar()is the Composition API way to$q(vue-composables/use-quasar.md).- Use
useInterval,useTimeout,useAnimationFrameinstead of native timers: they cancel on component destroy/deactivate and are SSR no-ops (vue-composables/use-interval.md:5-6; start server-side work outside the rendering lifecycle instead of registering a timer insetup()). Platform.isbooleans are explicitlyfalse, notundefined(since v2.17) and the dead flags (ie,winphone,kindle,silk,edgeChromium) are gone since v2.28. Test with=== false, never falsiness, if you must branch.
Layout and navigation
- Inside
QLayout, putQPullToRefreshas a direct child ofQPageand wrap the page content with it (vue-components/pull-to-refresh.md:214); callupdateScrollTarget()if you move its parent. QRouteTabhas nomodel-valueprop; its active state derives from the route (dist/api/QRouteTab.json). Do not wire v-model to it.- Menus that need
role="menu"(since v2.25): declare it on the wrappedQList; its actionableQItems then exposemenuitemroles automatically.
Theming
- Dark mode in SSR/SSG:
'auto'renders light on the server and resolves on the client, so dark users see a flash; if the preference is knowable server-side (cookie), call$q.dark.set()fromsrc/App.vuebefore mount (quasar-plugins/dark.md:93). - Colors: read/write brand colors with
getCssVar/setCssVar; palette lookup withgetPaletteColorfrom thecolorsutil. Since 2.33.1textToRgb()preserves the alpha ofrgb(R, G, B, A)strings (src/utils/colors/colors.js:149-174). - The LoadingBar plugin is the recommended way to show an Ajax progress bar
over manual
QAjaxBarinstances (vue-components/ajax-bar.md:16).
Validation
- Connect Regle (https://reglejs.dev/) to
QInput/fields for externalized validation; Quasar's docs recommend it (vue-components/input.md:2397).
Quasar CLI projects
- Import wrappers from
#q-app/wrappers(boot files,configure, store, router, SSR hooks);quasar/wrappersis the deprecated path (wrappers/index.js:9-16, docsquasar-cli-viteupgrade guide).