Not When Data ChangesâBut When Itâs Read: Understanding Dependency Collection vs Triggering in Vue
Dependency collection happens when reactive values are accessed during execution, allowing Vue to record which functions depend on them, while triggering occurs when those values change and Vue re-runs only the functions that previously accessed them.
Itâs tempting to think of Vueâs reactivity like this:
âWhen data changes, Vue updates the UI.â
That sounds right.
But it hides something important.
Because Vue doesnât actually react to data directly.
It reacts to relationshipsârelationships that only exist because of two quiet phases:
Dependency collection, and triggering.
To understand Vue, you have to see both.
Nothing Happens When Data Changes
Start with something simple:
const count = ref(0)
count.value++Nothing happens.
No UI update.
No reaction.
No side effect.
Which is strange, if you think Vue is âwatchingâ your data.
But Vue isnât watching anything.
Not yet.
The Missing Moment
Now place the same value inside a template:
<template>
<p>{{ count }}</p>
</template>Now something changes.
When count updates, the UI updates too.
So whatâs different?
Not the data.
The difference is:
The value was used
And thatâs where everything begins.
Dependency Collection: When Use Becomes a Relationship
When Vue renders your template, it doesnât just produce HTML.
It runs a function.
Something like:
function render() {
return count.value
}And while this function runs, Vue is quietly observing.
So when this line executes:
count.valueVue records a relationship:
âThis render function depends on countâThatâs dependency collection.
Not scanning code.
Not analyzing structure.
Just noticing:
âThis value was accessed, right now, during executionâ
And remembering it.
Not Everything Gets Collected
Now consider this:
<template>
<p v-if="show">{{ count }}</p>
</template>If show is false, then the render function behaves like:
function render() {
if (show.value) {
return count.value
}
}But since the condition is false:
show.valueis accessedcount.valueis not
So Vue records:
render depends on showEven though count exists in the template.
Even though it could run.
It didnât.
And thatâs enough.
Triggering: When Relationships Are Used
Now later:
count.value++Vue doesnât ask:
âWhat changed?â
It asks:
âWho depends on this?â
If no one ever used count, then no one depends on it.
So nothing happens.
But once count has been accessed during a render, Vue has a record:
count â render functionNow when it changes:
Vue re-runs the render
Thatâs triggering.
Not detection.
Not observation.
Just:
âYou used this before, so Iâll run you againâ
Read vs Write
At this point, the system becomes clearer.
There are only two moments that matter:
When something is read, and when something is written.
Reading creates the relationship.
Writing uses it.
The Shape of the System
If you compress everything, Vue is doing something surprisingly small:
During render:
âWhat did you read?â
During update:
âWho read this before?â
Thatâs it.
No magic.
No hidden watchers scanning your state.
Just a graph that is built as your code runs.
Why It Works This Way
You might wonder why Vue doesnât just track everything automatically.
Why not track all variables in the template?
Because that would mean:
- tracking values that are never used
- triggering updates that donât matter
- losing precision
Instead, Vue chooses something more dynamic:
Track only what actually happened
Not what could happen.
A Subtle Shift in Thinking
Itâs easy to say:
âVue tracks dataâ
But thatâs not quite true.
Vue tracks access to data
And that small shift explains everything:
- why
v-ifchanges dependencies - why unused values donât trigger updates
- why destructuring can break reactivity
Because without accessâ
there is nothing to collect.
And without collectionâ
there is nothing to trigger.
A Final Thought
Reactivity isnât about values changing.
Itâs about relationships being formed, and then honored later.
First, Vue listens to what your code touches.
Then, when something changes, it remembers:
âYou cared about this onceâ
And gives your code a chance to care again.