Vue essentials: 50 cards on the Composition API, reactivity and Pinia
Vue 3 fundamentals: ref vs reactive, computed and watch, props and emits, v-model, directives, slots, single-file components and Pinia stores.
Practice now
Study without an account
Scheduled with the default Askesis timings. Progress is saved in this browser.
All 50 cards
- 1What is the Composition API?Writing component logic with imported functions like
ref,computedandwatch, instead of the Options API’sdata,methodsandcomputedoptionsVue 3 supports both; the Composition API makes logic easier to reuse and to type. - 2What does
<script setup>do?Compile-time sugar for the Composition API: variables, functions and imports declared at its top level are usable directly in the template - 3What does
ref()return?A reactive object holding the value in.value; reading.valuetracks it, writing it triggers updatestsconst count = ref(0) count.value++ - 4Why don’t you write
.valuein templates?Top-level refs are unwrapped automatically in the template, so{{ count }}readscount.value - 5
ref()vsreactive()reactive()makes an object deeply reactive through a Proxy, with no.value, but only works on objects, arrays, Maps and Sets;ref()holds any valueThe Vue docs recommendref()as the default. - 6Why does
countstop updating?tsconst state = reactive({ count: 0 }) let { count } = stateDestructuring copies the current value into a plain variable, disconnected from the proxy. Keep usingstate.count, or destructuretoRefs(state) - 7Why shouldn’t you replace a whole
reactive()object?The template and watchers track the original proxy; assigning a new object breaks that link. Mutate its properties, or use arefand assign.value - 8What does
computed()do?Returns a read-only ref whose getter result is cached and only recomputed when one of its reactive dependencies changestsconst fullName = computed(() => first.value + " " + last.value) - 9A computed property vs a method called in the templateA computed value is cached until its dependencies change; a method runs again on every re-render
- 10What should a computed getter never do?Cause side effects: no mutating other state, async requests or DOM changes. Use a watcher for those
- 11
watchvswatchEffectwatchis lazy, watches explicit sources and passes new and old values;watchEffectruns immediately and tracks whatever reactive state it reads - 12Why doesn’t this watcher work?ts
const state = reactive({ count: 0 }) watch(state.count, (n) => console.log(n))state.countpasses a plain number, not a reactive source. Pass a getter:watch(() => state.count, …) - 13What do the
immediateanddeepwatch options do?immediate: truealso runs the callback once right away;deep: truefires on nested mutations tooWatching areactive()object directly is deep automatically. - 14How do you stop a watcher?Call the function that
watchorwatchEffectreturns; watchers created synchronously insetupstop automatically on unmount - 15Declare typed props in
<script setup>tsconst props = defineProps<{ title: string count?: number }>()definePropsis a compiler macro, so it needs no import. - 16Can a child component change a prop?No. Props flow one way, parent to child, and Vue warns on mutation; emit an event or copy the value into a local ref
- 17Is destructuring
defineProps()reactive?Since Vue 3.5, yes: the compiler rewritestitletoprops.title. To watch one, pass a getter:watch(() => title, …)Before 3.5, destructured props lost reactivity. - 18Declare and emit an event in
<script setup>tsconst emit = defineEmits<{ change: [id: number] }>() emit("change", 42)The parent listens with<Item @change="onChange" />. - 19What is
@in@click="save"?Shorthand forv-on:, which listens to DOM events or component events - 20What is
:in:src="url"?Shorthand forv-bind:, which binds an attribute or prop to a JavaScript expressionSince Vue 3.4,:srcalone means:src="src". - 21What does
v-modeldo on an<input>?Two-way binding: it sets the input’s value and updates the variable on everyinputevent - 22What does
v-modelexpand to on a component?AmodelValueprop plus a listener for theupdate:modelValueeventhtml<Search v-model="query" /> <!-- is short for --> <Search :modelValue="query" @update:modelValue="query = $event" /> - 23What does
defineModel()do?Since Vue 3.4, it declares thev-modelprop and event for you and returns a ref; assigning to it updates the parenttsconst model = defineModel<string>() model.value = "new text" - 24
v-modelmodifiers.lazy,.number,.trim.lazysyncs onchangeinstead ofinput;.numbercasts the value to a number;.trimstrips surrounding whitespace - 25
v-ifvsv-showv-ifcreates and destroys the element;v-showalways renders it and toggles CSSdisplayPreferv-showfor things toggled often,v-iffor conditions that rarely change. - 26Render a list with
v-forhtml<li v-for="todo in todos" :key="todo.id"> {{ todo.text }} </li>Use a stable uniquekey, not the index, when items can be reordered or removed. - 27What happens with
v-ifandv-foron the same element?In Vue 3,v-ifis evaluated first, so it can’t see the loop variable. Filter with a computed, or movev-forto a wrapping<template>Vue 2 had the opposite priority. - 28What does this render?html
<span v-for="n in 3">{{ n }}</span>Three spans containing 1, 2 and 3: a number range inv-forstarts at 1, not 0 - 29What do
.preventand.stopdo on an event?.preventcallsevent.preventDefault();.stopcallsevent.stopPropagation()Example:@submit.prevent="send". Key modifiers work too:@keyup.enter="send". - 30Why is
v-htmlrisky?It inserts raw HTML, so user-supplied content can inject scripts (XSS);{{ }}interpolation always escapes text - 31Toggle classes with
:classhtml<div :class="{ active: isActive, 'text-error': hasError }"></div>Arrays work too::class="[base, { active: isActive }]". - 32What can go inside
{{ }}?A single JavaScript expression, likeok ? "Yes" : "No"; statements such asiforletaren’t allowed - 33Default and named slotshtml
<!-- Card.vue --> <header><slot name="header" /></header> <slot>Fallback content</slot> <!-- Parent --> <Card> <template #header>Title</template> Body text </Card>#headeris shorthand forv-slot:header. - 34What is a scoped slot?A slot that passes data from the child back to the parent’s slot contenthtml
<!-- List.vue --> <slot :item="item" /> <!-- Parent --> <List v-slot="{ item }">{{ item.name }}</List> - 35What goes in a single-file component (
.vuefile)?A<template>, a<script>or<script setup>block and optional<style>blocks, compiled by a build tool such as Vite - 36What does
<style scoped>do?The compiler adds adata-v-…attribute to the component’s elements and rewrites its selectors, so the CSS applies only to this componentA child component’s root element is still styled by the parent’s scoped CSS. - 37Which lifecycle hook is the first that can access the DOM?
onMounted; undo timers and listeners inonUnmounted - 38Get a reference to a DOM elementts
// template: <input ref="search" /> const search = useTemplateRef<HTMLInputElement>("search") onMounted(() => search.value?.focus())useTemplateRefis Vue 3.5+; before that, declareconst search = ref(null)with the same name. It isnulluntil mounted. - 39What is
nextTick()for?Waiting until Vue has applied pending DOM updates after a state change:await nextTick()Vue batches DOM updates and applies them asynchronously. - 40What are
provideandinject?A way for an ancestor to pass data to any descendant without prop drillingtsprovide("theme", theme) // in an ancestor const theme = inject("theme", "light") // in a descendant, with a default - 41What is a composable?A function, named
useSomethingby convention, that uses the Composition API to package and reuse stateful logictsexport function useCounter() { const count = ref(0) const inc = () => count.value++ return { count, inc } } - 42Why can’t a parent call a
<script setup>child’s function through a template ref?<script setup>components are closed by default; the child must list what it shares withdefineExpose({ reset }) - 43What is attribute fallthrough?Attributes and listeners not declared as props or emits, like
class,styleandid, are added to the component’s root elementTurn it off withdefineOptions({ inheritAttrs: false })and read them withuseAttrs(). - 44Create and mount a Vue 3 app with Piniats
const app = createApp(App) app.use(createPinia()) app.mount("#app") - 45What is Pinia?Vue’s official state management library and the successor to Vuex: stores with state, getters and actions, fully typed and devtools-friendly
- 46Define a Pinia setup storets
export const useCartStore = defineStore("cart", () => { const items = ref<Item[]>([]) const count = computed(() => items.value.length) function add(item: Item) { items.value.push(item) } return { items, count, add } })Refs become state, computeds become getters, functions become actions. Return every piece of state. - 47Why doesn’t
countupdate?tsconst store = useCounterStore() const { count } = storeDestructuring a store breaks reactivity. Useconst { count } = storeToRefs(store); actions can be destructured directly - 48How does Vue 3 track reactivity?With JavaScript Proxies for
reactive()and getters/setters forref(); effects record what they read and re-run when it changesThat is why adding a new property or setting an array index is reactive in Vue 3, unlike Vue 2. - 49What does
shallowRef()do?Only assigning.valueis reactive; changes inside the value aren’t tracked. Useful for large or external objects - 50What does
<Teleport to="body">do?Renders its content into another DOM node, such asbody, while it stays logically part of the component; handy for modals
Frequently asked questions
Does this deck use the Options API or the Composition API?
The Composition API with script setup, which is what the Vue docs and most new projects use. The concepts behind directives, props and slots are the same in both.
Which Vue version does it cover?
Vue 3, including newer additions such as defineModel (3.4), reactive props destructure and useTemplateRef (3.5).
Should I use ref or reactive?
The Vue docs recommend ref as the default: it works with any value and survives destructuring and reassignment. reactive is fine for objects you only mutate in place.
Is Pinia required?
No. Small apps can share state with composables or provide and inject. Pinia adds devtools support, SSR safety and a consistent structure for larger apps.
More in Web development
HTML & CSS
Fifty HTML and CSS cards: semantic HTML and accessible forms, specificity and cascade layers, flexbox and grid, stacking contexts and z-index, modern units and container queries.
50 cardsReact
Fifty React cards: state and re-rendering, useEffect and cleanup, memoization, refs, context, Suspense and the React 19 APIs like use, useOptimistic and useActionState.
50 cardsAngular
Modern Angular: standalone components, signals, inputs and outputs, dependency injection, RxJS basics, @if and @for, routing and OnPush change detection.
50 cardsNext.js
Next.js App Router basics: server vs client components, layouts, route handlers, server actions, caching, metadata, dynamic routes and middleware.
50 cardsNode.js
Node.js fundamentals: the event loop, ESM vs CommonJS, npm, streams, Buffer, fs/promises, process, error handling, worker threads and a basic HTTP server.
50 cardsGraphQL
GraphQL basics: schema types, queries, mutations, subscriptions, resolvers, variables, fragments, N+1 and DataLoader, introspection and GraphQL vs REST.
50 cards