💚 Vue.js Advanced

How does Vue 3's Proxy-based reactivity system work internally?

Why Interviewers Ask This

Advanced questions like this reveal whether a candidate has internalized Vue.js deeply enough to make architectural decisions. Strong answers demonstrate both breadth and depth of experience.

Answer

Vue 3's reactivity is powered by ES2015 Proxy, which intercepts all operations on an object. Core implementation: (1) reactive(obj): wraps obj in a Proxy with handlers for get, set, deleteProperty, has, and ownKeys traps; (2) Track (in get trap): when a property is read, Vue calls track(target, "get", key) — this records that the currently running effect (computed/watch) depends on this property. Dependencies are stored in a WeakMap: target → Map: key → Set<Effect>; (3) Trigger (in set/delete trap): when a property is written, Vue calls trigger(target, "set", key) — this finds all effects that depend on this target.key and re-runs them; (4) ref(val): a ref is an object with a .value getter/setter. The getter calls track(), the setter calls trigger(). For object values, ref wraps them in reactive(). Primitives don't need Proxy — just get/set interception; (5) computed(fn): creates an effect that only re-runs when its dependencies change. Lazy — only evaluates when read. Caches result; re-evaluates when dependencies change; (6) Effect: a function (watcher/computed) that runs within a tracked context. During execution, all reactive reads are recorded as dependencies. Nested effects: Vue maintains an active effect stack — computed within a watch works correctly. Raw access: toRaw(proxy) — access the original object without tracking. markRaw(obj) — prevent object from being made reactive.

Common Mistake

Don't just define the term — demonstrate that you understand when to use it and when not to. Showing awareness of trade-offs is what separates average from strong Vue.js candidates.