I will address only the specific question how does vue.js know which dependencies affect which computed property?
The simple answer is that each time vue evaluates a computed property it creates a map of all the reactive properties that were accessed in the span of that call. The next time any of these reactive properties change they will trigger a reevaluation of the computed property.
If during the most recent evaluation of a computed property, one of its reactive dependencies is never reached (maybe because it is within the non-traveled path of an if/else construct), subsequent changes to that reactive property will not trigger a reevaluation of the computed property.
Observe this behavior by modifying the two reactive properties in this fiddle (by simply typing in their corresponding input boxes). A few things to note:
- the
calledcomputed property is evaluated once on document load (it’s triggered because it’s rendered in the template). - because the
pathis set to1the reactive property that will be mapped as a dependency isval1. As a result it will be the only one that can trigger a reevaluation ofcalledwhen it changes. The value ofval2can also change but will not have the same effect oncalled, even though it’s clearly present in the function. - When you click on the “Change Path” button,
pathis toggled from1to2. - right after the path switch, note that a change to
val1will affectcalledonly once more. Becausepathhas been set to2prior to that last reevaluation,val1will not be reachable and will not be mapped as a dependency ofcalledany longer. Subsequent changes to its value won’t trigger a reevaluation ofcalledfrom that point on. But thenval2has now been mapped as a dependency ofcalledand changes to it trigger the reevaluation the same way they did forval1earlier. It will be so until the next path toggle from2back to1.
Here’s the code.
let path=1
let count=0
const vm=new Vue({
el:"#app",
data:{
val1:null,
val2:null,
},
computed: {
called: function(){
if (path==1){
this.val1
}
if (path==2){
this.val2
}
return "I was just called "+ ++count +" times"
}
},
methods: {
changePath(){
path = path==2 ? 1 : 2
}
}
})
and corresponding template
<div id="app">
<input v-model="val1"/> {{val1}}
<br>
<input v-model="val2"/> {{val2}}
<br>
<button @click="changePath">change path</button>
<br>
{{ called }}
</div>