v-memo & v-once — Series 3

Preview — 3 of 10 questions

Why does this list scramble input values when reordered, even though every item has a :key?

javascript
<template>
  <input v-for="item in items" :key="item.category" v-model="item.name" />
</template>
A:key has no effect on <input> elements specifically — only on elements like <li> or <div>
Bv-model is incompatible with :key on the same element — this is invalid syntax
CThis works correctly as written — any string value is equally valid as a :key, unique or not
Ditem.category is being used as the key, but multiple items commonly share the same category — a :key only helps Vue correctly track identity when it's actually unique per item. With duplicate keys, Vue can't reliably tell which DOM node corresponds to which item during a reorder, and ends up reusing/patching input elements incorrectly, so a given <input>'s in-progress typed value (and even its native focus state) can end up attached to the wrong underlying item after the list changes

Why is version B likely faster than version A for a large list, even though both produce the same rendered output?

javascript
<!-- Version A: a method called once per item, every render -->
<li v-for="item in items" :key="item.id">{{ formatPrice(item) }}</li>

<!-- Version B: one computed producing all formatted values up front -->
<li v-for="item in formattedItems" :key="item.id">{{ item.formattedPrice }}</li>
AThere's no real performance difference — both approaches call formatPrice exactly the same number of times, on every single render
BVersion A is actually faster, since it avoids the memory overhead of storing a second, formatted copy of the array
Cv-for iterating over a computed array is invalid — formattedItems in version B would need to be a plain ref, not a computed
DVersion A calls formatPrice(item) fresh on every component re-render, for every item, regardless of whether items actually changed — a method invoked from a template has no caching of its own. Version B's computed only re-runs (recomputing every item's formatted price) when items itself actually changes, and is otherwise served from cache — so for a component that re-renders for reasons unrelated to items (a sibling prop changing, a parent re-rendering), version B skips re-formatting the entire list while version A redundantly redoes it every time

Why specify include here instead of caching every dynamic component by default?

javascript
<KeepAlive :include="['ProductList', 'ProductDetail']">
  <component :is="currentView" />
</KeepAlive>
Ainclude is required syntax — <KeepAlive> without it caches nothing at all, defeating its purpose
Binclude only affects which components show a loading spinner while being cached, not whether they're actually cached
CWithout include (or its counterpart, exclude), <KeepAlive> caches every component instance it ever renders as currentView changes — for an app with many possible views, some rarely visited and heavy to keep in memory, that means holding onto potentially dozens of full component instances (their state, their DOM) indefinitely. Naming specific components via include limits caching to just the views where preserving state (like ProductList's current scroll position and filters) genuinely matters, letting rarely-cached, heavier views mount and unmount normally instead of accumulating in memory forever
Dinclude is purely cosmetic — it has no effect on either behavior or memory usage, only on how components appear in Vue DevTools

Sign up free to play

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