Vue's promise: you describe what the screen should say and it keeps the page in step. One idea pays for it: reactivity. A reactive value records who read it, and writing to it re-runs exactly those readers — your component's render function among them. Nothing is diffed; Vue watched those properties being read. Almost every Vue-specific bug is a place where that link was quietly cut: a value copied out of its container, a dependency read after an await, a variable rebound. Learn where the link lives and the rest follows. Everything below was executed against Vue 3.5.40 first.
Each chapter opens with the short version. Tap one to read the detail.
Reactivity: what Vue is actually watching
~2 min
Vue tracks property reads, not values. ref() puts a value in a box you read through .value; reactive() wraps an object in a Proxy that intercepts every get and set. The subscription belongs to the container — copy a value out and the copy is an ordinary number that never updates again.
Derived values, and the watchers you mostly don't need
~2 min
computed() is lazy and cached: the getter runs only when something reads it and a dependency changed. A watcher exists for effects — a request, a timer, imperative work. If you can name the value you want, it is a computed; a watcher is for what happens, not what is.
The template language
~3 min
A template is not HTML with holes: it compiles to a render function, and each binding is one JavaScript expression evaluated in a sandbox. Directives read v-name:arg.modifier="value". Three decide most of a page's behaviour: v-if creates and destroys, v-for needs a stable key, and v-model is two bindings wearing one name.
Single-file components, and which API to write them in
~2 min
<script setup> is the setup function: top-level bindings reach the template with no return statement, and the block runs once per instance. defineProps, defineEmits and defineModel are compiler macros, not imports. For new code write the Composition API; the Options API is supported indefinitely, not deprecated.
The component contract: props, events, slots, injection
~3 min
A prop is read-only — assigning to one warns target is readonly. Anything undeclared falls through onto the child's root element. Slot content is compiled in the parent's scope, whatever child renders it. Injection reaches past the components between, but stays live only if you provided a container.
Instances: creation, mounting, and template refs
~2 min
Every use of a component is a separate instance with its own state. <script setup> is the creation stage: no elements exist yet and a template ref is still null. A hook attaches to whichever instance is active when you register it, which is why one registered from a callback attaches to nothing.
Reuse: composables, and the narrower tool beside them
~2 min
A composable is a plain function using the reactivity APIs, called synchronously at the top of setup — that call binds its hooks and watchers to your component. Return refs, not values, so the caller can destructure without losing reactivity. Custom directives are the narrower tool, for raw element access.
The built-ins worth knowing
~2 min
Four components you would otherwise reinvent badly. <Transition> adds enter and leave classes around a single element; <KeepAlive> caches an instance instead of destroying it; <Teleport> moves the node without moving the component; <Suspense> waits on async setup and is still marked experimental.
Scaling up: routing and shared state
~2 min
Vue Router maps paths to components rendered inside <RouterView>; useRoute() is the reactive current location and useRouter() is what you navigate with. A Pinia store is a reactive object — so destructuring one loses reactivity for exactly the reason the first chapter gave, and storeToRefs is the fix.
How updates get cheap, and where they get expensive
~2 min
Vue compiles your template rather than merely reading it, so the runtime already knows which nodes can change and which bindings on them. Most slowness left after that is yours: props rebuilt every render, deep reactivity over huge data, or simply too many nodes on the page.
Written by Keentune. We are not affiliated with or endorsed by the organizations whose documentation informs this guide, and any linked sources belong to their respective owners.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.