Vue 12: Reactivity Fundamentals
easy⏱ 5 mincoursevue
Proxies: track and trigger
Every property read that happens while a computed getter or a watchEffect function is running gets recorded as a dependency of that effect. When you later write to one of those tracked properties — even through a plain assignment like state.quantity++ — Vue's Proxy set trap fires, looks up which effects depend on that property, and reruns them. This dependency graph is rebuilt on every run, so it automatically adapts if your code takes a different branch.
import { reactive, computed, watchEffect } from 'vue';
const state = reactive({ a: 1, b: 2 });
// Reading state.a and state.b here TRACKS both as dependencies.
const sum = computed(() => state.a + state.b);
watchEffect(() => {
console.log('sum is now', sum.value); // re-runs whenever sum changes
});
state.a = 10; // TRIGGERS: sum recomputes, watchEffect logs again
It's Proxy get/set traps, not polling
Vue never polls or diffs your data to detect changes — that would be slow and imprecise. The Proxy's get trap does the tracking at read-time, and its set trap does the triggering at write-time, both synchronously, both exact. This is why plain object/array mutation (push, splice, direct property assignment) just works with reactive(), unlike older patterns that require immutable updates.
Trace the reactivity chain
Run the demo and click +1 quantity a few times. Then add a state.price++ button too, and confirm both buttons drive the SAME computed and the SAME watch — because both properties are dependencies of total.