From my notes

Most important

Questions and flashcards from your Important note — reactivity and the event loop, the track and trigger engine, ref versus reactive, computed caching, watchers and flush timing, and the app lifecycle for client rendering, SSR and hydration, updates and unmount. Every question here is marked important and trained first.

Written from your Important note, the condensed version of the topics you marked as most important. All 32 questions carry the Important badge: train only these. The longer study pages behind them are Essentials: templates and reactivity, Essentials: rendering, events and forms and Reactivity system.

Know

  • Reactivity and the event loop: state changes synchronously; re-rendering is a job flushed in a microtask; nextTick() waits for that flush.
  • The engine: track and trigger, the WeakMap → Map → Set structure, why reads outside effects are ignored, and finishing the trigger your note left empty.
  • ref versus reactive: what a RefImpl is, reassigning .value, what destructuring keeps and what it loses, the limits of reactive().
  • Computed: ComputedRefImpl, the dirty flag, lazy recomputation, cache invalidation, writable computeds.
  • Watchers: laziness and immediate, deep by default for reactive objects and shallow for getters, what watchEffect tracks around await, pre, post and sync flushing, and cleanup.
  • Lifecycle: the hook list, the client mount order, SSR and hydration with Nuxt's payload, the order of an update, and what unmount does and does not clean up.

Fact check of your notes

The Important note is accurate on almost everything. These are the places where the questions follow the documentation instead.

Gotcha· Changes are synchronous, recomputation is not

The note opens with "when a reactive value changes, it is recomputed right away". The value changes right away. Computeds that depend on it are only marked dirty and recompute when read, and the DOM update waits for the microtask flush.

Gotcha· A Set has add(), not set()

In track(), propertySubscribers.set(activeSubscriber) throws "set is not a function". It is propertySubscribers.add(activeSubscriber). trigger() and reactive() are still empty, and new Proxy(targer, …) has a typo; finishing them is the exercise below.

Gotcha· The subscriber lists belong to the data, not the component

The note says track subscribes the component "where the component keeps everyone that is subscribed to it". It is the other way round, as your code shows: the map is keyed by the reactive object and property, and holds the effects (renders, computeds, watchers) that read them.

Gotcha· What I can destructure means for refs

"I can destructure" is true for an object of refs, such as a composable's return value: each ref keeps tracking. Destructuring .value out of a ref copies the current value and loses reactivity, just like destructuring a reactive() object.

Gotcha· onRenderTracked, not onRenderTracker

The debug hooks are onRenderTracked and onRenderTriggered, and both only run in development.

Exercise

Exercise
  • Finish the engine in your Important note: fix add, write trigger, write reactive() with get and set traps, and an effect(fn) that sets activeSubscriber. Prove that changing a nested property re-runs the effect.
  • In a playground, log inside a computed, a default watcher, a post watcher, onBeforeUpdate and onUpdated, then change a ref twice in one handler. Compare the order with the "Updates" section of your note.
  • Explain SSR and hydration in Nuxt out loud in under two minutes, mentioning the payload, and record yourself.

Be able to say

Be able to say· How does Vue's reactivity engine know what to update?

"While a render function, computed or watcher runs, it is the active subscriber. Every reactive read goes through a getter or a Proxy trap that calls track, which records the active subscriber in a WeakMap keyed by the object, then a Map by property, then a Set of subscribers. Reads outside an effect are ignored, because nothing could be re-run. A write calls trigger, which looks up that set and schedules each subscriber. The WeakMap lets unused objects be garbage collected."

Be able to say· What is the difference between ref and reactive?

"reactive() wraps an object in a Proxy that tracks every property; it only takes objects, and you cannot reassign or destructure it without losing reactivity. ref() is a small object whose .value getter and setter track and trigger, so it can hold primitives; an object inside it is made reactive. Reassigning .value keeps everything updating, and refs can be passed around or returned from composables in plain objects. I default to ref."

Be able to say· How does a computed's cache work?

"A computed is both a subscriber and a dependency. While its getter runs it records its inputs; templates and watchers that read it subscribe to it. When an input changes it does not recompute, it marks itself dirty and notifies its readers. The next read sees the flag, recomputes, caches and clears it. If nothing reads it, it never recomputes. That makes it cheaper than a method, and it is why the getter must be pure."

Be able to say· When do watch and watchEffect run, and what do flush modes change?

"watch is lazy unless immediate, watches explicit sources, deep for a reactive object and shallow for a getter, and passes new and old values. watchEffect runs immediately and tracks what it reads synchronously, so not after an await. By default both run in the pre flush, after the synchronous code and before the DOM update. post runs after the DOM update, for measuring or charts. sync runs on every single change, so I avoid it for anything that changes in loops. Cleanup with onWatcherCleanup runs before the next run or when the watcher stops."

Be able to say· Walk me through a client-side mount and an SSR hydration.

"Client side: main.ts creates the app and calls mount. Each component runs setup and onBeforeMount, renders its VNodes, and the renderer creates elements, recursing into child components. The whole tree is built in memory and inserted into #app at the end, then onMounted runs, deepest child first. With SSR the server only runs setup and rendering and sends HTML plus, in Nuxt, a payload with fetched data and public config. The browser paints that HTML immediately. Hydration then runs setup and render again but reuses the existing DOM, attaching listeners and state, and reports a mismatch if the output differs. After that it is a normal SPA."

Be able to say· What does Vue clean up when a component unmounts, and what not?

"onBeforeUnmount runs, the DOM is removed, onUnmounted runs, and Vue stops everything it owns: the component's watchers and computeds created during setup and its template listeners. It does not know about intervals, timeouts, listeners on window or document, observers or third-party instances, so I remove those in onUnmounted or use composables that clean up after themselves."

Your notes

Open in Notes

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