I have this Vue.js code:
new Vue({
data:{
myValue:'x',
myOtherValue:'y'
},
computed: {
myComputed: myFunction(){
return this['my' + 'Value']
}
}
})
As you can see the computed property will be cached and it is depended only on data.myValue
. My question is how Vue.js caching system knows that run the computed function again only if myValue
is changed?
If I change the myOtherValue
variable, the myComputed
function will use the cache, and will not be run again will I call it.
I thought about several ways how it is possible. But how Vuejs doing that? I have read this article: https://vuejs.org/v2/guide/computed.html and found no answer.
And what happen in this code, what it will be depeneded on?
const flag=2
new Vue({
data:{
myValue:'x',
myOtherValue:'y'
},
computed: {
myComputed: myFunction(){
if (flag==1){
return this['my' + 'Value']
}
else
return this['my' + 'Other' + 'Value']
}
}
})
Bonus: I will appreciate I link to the relevant function in the VueJS code: https://github.com/vuejs/vue
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:
called
computed property is evaluated once on document load (it's triggered because it's rendered in the template).path
is set to1
the reactive property that will be mapped as a dependency isval1
. As a result it will be the only one that can trigger a reevaluation ofcalled
when it changes. The value ofval2
can also change but will not have the same effect oncalled
, even though it's clearly present in the function.path
is toggled from1
to2
.val1
will affectcalled
only once more. Becausepath
has been set to2
prior to that last reevaluation,val1
will not be reachable and will not be mapped as a dependency ofcalled
any longer. Subsequent changes to its value won't trigger a reevaluation ofcalled
from that point on. But thenval2
has now been mapped as a dependency ofcalled
and changes to it trigger the reevaluation the same way they did forval1
earlier. It will be so until the next path toggle from2
back to1
.Here's the code.
and corresponding template
It's the reactivity system of Vue.js, not a caching system.
The data in a component will be convert to getters and setters. When you access a value via a getter, the getter will add it to the dependencies, and when you modify the value via a setter, the setter will notify everyone who depends on the value.
Here is the source code, all the magic happens in this function: https://github.com/vuejs/vue/blob/dev/src/core/observer/index.js#L131
From the docs it reads that: Computed properties are cached, and only re-computed on reactive dependency changes. However the following fiddle shows something a bit different.
From the fiddle if you set the flag to 2, the computed property will be re-evaluated and executed if you change
myOtherValue
, however this will not happen if the flag is set to 1. I think it keeps track of your if conditions.In the docs usually you can find links to the relevant source code. Here is the code for computed properties: