ref() vs reactive(): Vue Reactivity Deep Dive
Purpose
This guide clears up common misunderstandings around Vue's ref()
and reactive()
and helps you choose the right tool for your situation.
The Core Difference
ref()
wraps any value (primitive or object) in a reactive container.reactive()
turns an object or array into a deeply reactive proxy.
ref()
const count = ref(0); // count.value === 0
const state = ref({ x: 1 }); // state.value.x === 1
reactive()
const state = reactive({ x: 1 });
console.log(state.x); // 1
When using
ref()
, always access the value with.value
. Withreactive()
, you access fields directly.
Why It’s Confusing
ref()
is also used to reference DOM elements in the template.ref(store.something)
doesn't "track"store.something
— it just copies the value once.- You get awkward
.value.prop
or.value[index]
syntax when wrapping complex types withref()
.
Practical Guidelines
Use ref()
:
- For primitive values (number, string, boolean)
- For tracking a DOM element or component (
ref(null)
+ref="el"
in template) - When you need a single reactive wrapper for any value (deep or shallow)
Use reactive()
:
- When dealing with objects or arrays
- When you want cleaner syntax (
state.prop
instead ofstate.value.prop
)
Use computed()
:
- When you want to derive a value reactively
- When
ref()
would give you a stale snapshot
Gotchas
Case | Don't Do This | Do This Instead |
---|---|---|
Want to track store value | ref(store.count) | computed(() => store.count) |
Want reactive object | ref({ a: 1 }) | reactive({ a: 1 }) |
Watch a field | watch(refObj.a, ...) | watch(() => refObj.a, ...) |
Analogy
ref()
is a box that holds a value. You must open the box with.value
.reactive()
is a live object where all properties are already reactive.computed()
is a window that always shows the current value.
Summary Table
Feature | ref() | reactive() | computed() |
---|---|---|---|
Syntax | .value required | direct access | read-only |
Deep reactivity | Yes (but annoying) | Yes | N/A |
Best for | Primitives, DOM refs | Objects, arrays | Derived values |
Final Tip
If you’re ever unsure which one to use:
- Is it a primitive? →
ref()
- Is it an object or array? →
reactive()
- Do you need a live-updating value based on another? →
computed()