Vue Reactivity System
Vue's reactivity system is the mechanism by which Vue automatically tracks which reactive data a component reads during render and re-renders only when that data changes — without any explicit subscription wiring from the developer.
Vue's reactivity system is the mechanism by which Vue automatically tracks which reactive data a component reads during render and re-renders only when that data changes — without any explicit subscription wiring from the developer.
Vue 3's reactivity is built on ES6 Proxy objects. When you call reactive({ count: 0 }) or ref(0), Vue wraps the value in a Proxy that intercepts get and set traps. During any reactive computation — rendering a component, evaluating a computed property, or running a watchEffect — Vue activates a global active effect tracker. Every get trap fires the track() function, which registers the current active effect as a subscriber of that specific property. This is dependency tracking, and it happens automatically just by reading the value.
When a reactive property is mutated (state.count++), the Proxy fires the set trap, which calls trigger(). trigger() looks up the subscriber list for that property and schedules all registered effects to re-run. Component render effects are scheduled on the microtask queue via Promise.resolve() to batch multiple synchronous mutations into a single re-render. This is why nextTick() resolves after all pending DOM updates — it resolves after the flushed microtask queue.
computed properties are lazy — they re-evaluate only when accessed and only when their tracked dependencies have changed since the last evaluation. watch and watchEffect run effects with configurable flush timing: flush: 'pre' (before DOM update), flush: 'post' (after DOM update, useful for DOM access), or flush: 'sync' (immediately on mutation, rare). This contrasts with React's model where React Rendering Lifecycle is explicit about scheduling via hooks. Vue's proxy-based approach means no need for manual dependency arrays — but it requires reactive values to remain accessed through the proxy (destructuring breaks reactivity unless you use toRefs).
Understanding this system explains the toRef, toRefs, storeToRefs, and shallowReactive APIs that preserve or limit reactive proxy wrapping.