shallowRef & markRaw — Series 3

Preview — 3 of 10 questions

Why does this row fail to update its displayed price after item.price changes, even though the rest of the row correctly re-renders?

javascript
<li v-for="item in items" :key="item.id" v-memo="[item.name]">
  {{ item.name }} — ${{ item.price }}
</li>
Av-memo="[item.name]" tells Vue to skip re-rendering this element entirely unless item.name specifically changes — since item.price isn't included in the dependency array, Vue has no reason to know it needs to re-render when only the price changes, so the memoized subtree (including the interpolated ${{ item.price }} text) keeps showing its old, stale value until something that is in the array (item.name) actually changes too
Bv-memo only ever accepts a single-element dependency array — this code is invalid and falls back to re-rendering on every change regardless
Cv-memo is purely a development-mode debugging aid with zero effect on production builds — this bug would only appear during local development
Dv-memo requires every reactive value used anywhere in its element to be a ref, not a plain object property — item.price being read off a plain object is what's causing the staleness here

Does using v-show instead of v-if avoid HeavyDashboards expensive `onMounted` setup work while its hidden?

javascript
<HeavyDashboard v-show="activeTab === 'dashboard'" />
Av-show and v-if behave identically here — both defer HeavyDashboard's mounting (and its onMounted hook) until the condition first becomes true
Bv-show never actually mounts HeavyDashboard at all until it becomes visible — this code as written can never run onMounted's expensive setup while hidden
Cv-show mounts HeavyDashboard immediately, regardless of whether activeTab === 'dashboard' is currently true — it only toggles CSS display afterward. That means onMounted's expensive chart initialization and data fetch run right away, the moment HeavyDashboard first appears anywhere in the render tree, even while it's invisible — the opposite of what v-if would do (deferring the whole mount, including this setup work, until the condition first becomes true)
Dv-show's performance characteristics depend entirely on whether HeavyDashboard uses <script setup> versus the Options API

Why might lazy-loading dozens of small, related components individually hurt performance rather than help it?

javascript
// Twelve separate, tiny lazy components, each its own network request
const Icon1 = defineAsyncComponent(() => import('./icons/Icon1.vue'))
const Icon2 = defineAsyncComponent(() => import('./icons/Icon2.vue'))
// ... ten more, each a few lines of SVG
AThere's no real downside — more, smaller chunks are always strictly better than fewer, larger ones, regardless of how many there are
BdefineAsyncComponent has a hard limit of 10 concurrent lazy components per page; the 11th and beyond silently fail to load
CThis code has a syntax error — defineAsyncComponent cannot be called more than once per file
DSplitting a set of genuinely tiny, closely-related pieces (a dozen small icon components, likely to be needed together) into a dozen separate chunks means a dozen separate HTTP requests when they're actually used — each with its own request overhead (headers, a round-trip, connection/multiplexing limits) that can outweigh the download-size savings for content this small. Bundling small, related pieces together into one shared chunk (importing them from one module, or using matching chunk-name hints to merge them) often performs better than maximally fragmenting every last piece into its own separate lazy-loaded unit

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.