vuejs 是如何知道 computed 属性 缓存的依赖关系的?
How vuejs knows the depenedencies of computed property for caching?
我有这个 Vue.js 代码:
new Vue({
data:{
myValue:'x',
myOtherValue:'y'
},
computed: {
myComputed: myFunction(){
return this['my' + 'Value']
}
}
})
如您所见,计算出的 属性 将被缓存并且仅依赖于 data.myValue
。我的问题是 Vue.js 缓存系统如何仅在 myValue
更改时再次知道 运行 计算函数?
如果我更改 myOtherValue
变量,myComputed
函数将使用缓存,并且不会 运行 再次调用它。
我想过几种可能的方法。但是 Vuejs 是怎么做到的呢?
我已阅读这篇文章:https://vuejs.org/v2/guide/computed.html,但没有找到答案。
这段代码中发生了什么,它将依赖什么?
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']
}
}
})
奖励: 我会感谢我 link VueJS 代码中的相关功能:https://github.com/vuejs/vue
这是Vue.js的反应系统,不是缓存系统。
组件中的数据将被转换为getters和setters。当您通过 getter 访问一个值时,getter 会将其添加到依赖项中,而当您通过 setter 修改该值时,setter 会通知所有人取决于价值。
这是源代码,所有的魔法都发生在这个函数中:https://github.com/vuejs/vue/blob/dev/src/core/observer/index.js#L131
从文档中可以看出:
计算的属性被缓存,并且仅在反应性依赖项更改时重新计算。
然而下面的 fiddle 显示了一些不同的东西。
从 fiddle 如果您将标志设置为 2,如果您更改 myOtherValue
,计算的 属性 将被重新计算并执行,但是如果标志设置为 1。我认为它会跟踪您的 if 条件。
在文档中通常可以找到相关源代码的链接。
这是计算属性的代码:
我将只解决具体问题 vue.js 如何知道哪些依赖项影响哪些计算 属性?
简单的答案是,每次 vue 评估一个计算 属性 时,它都会创建一个映射,其中包含在该调用范围内访问的所有响应式属性。下次这些反应性属性中的任何一个发生变化时,它们将触发对计算 属性 的重新评估。
如果在计算的 属性 的最近评估期间,它的一个反应性依赖项从未达到(可能是因为它在 if/else 构造的非行进路径内),随后对该反应 属性 的更改不会触发对计算的 属性.
的重新评估
通过修改此 fiddle 中的两个反应属性来观察此行为(只需在相应的输入框中键入)。需要注意的几点:
called
计算 属性 在文档加载时计算一次(它被触发是因为它在模板中呈现)。
- 因为
path
设置为 1
,将映射为依赖项的反应式 属性 是 val1
。因此,它将是唯一可以在 called
发生变化时触发重新评估的对象。 val2
的值也可以更改,但不会对 called
产生相同的影响,即使它明确存在于函数中。
- 当您单击 "Change Path" 按钮时,
path
从 1
切换到 2
。
- 在路径切换之后,请注意对
val1
的更改只会再次影响 called
。由于 path
在上次重新评估之前已设置为 2
,因此 val1
将无法访问,并且将不再映射为 called
的依赖项。此后对其值的后续更改不会触发 called
的重新计算。但是 val2
现在已被映射为 called
的依赖项,并且对它的更改会触发重新评估,就像之前对 val1
所做的一样。直到下一个路径从 2
切换回 1
。
这是代码。
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
}
}
})
和相应的模板
<div id="app">
<input v-model="val1"/> {{val1}}
<br>
<input v-model="val2"/> {{val2}}
<br>
<button @click="changePath">change path</button>
<br>
{{ called }}
</div>
我有这个 Vue.js 代码:
new Vue({
data:{
myValue:'x',
myOtherValue:'y'
},
computed: {
myComputed: myFunction(){
return this['my' + 'Value']
}
}
})
如您所见,计算出的 属性 将被缓存并且仅依赖于 data.myValue
。我的问题是 Vue.js 缓存系统如何仅在 myValue
更改时再次知道 运行 计算函数?
如果我更改 myOtherValue
变量,myComputed
函数将使用缓存,并且不会 运行 再次调用它。
我想过几种可能的方法。但是 Vuejs 是怎么做到的呢? 我已阅读这篇文章:https://vuejs.org/v2/guide/computed.html,但没有找到答案。
这段代码中发生了什么,它将依赖什么?
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']
}
}
})
奖励: 我会感谢我 link VueJS 代码中的相关功能:https://github.com/vuejs/vue
这是Vue.js的反应系统,不是缓存系统。
组件中的数据将被转换为getters和setters。当您通过 getter 访问一个值时,getter 会将其添加到依赖项中,而当您通过 setter 修改该值时,setter 会通知所有人取决于价值。
这是源代码,所有的魔法都发生在这个函数中:https://github.com/vuejs/vue/blob/dev/src/core/observer/index.js#L131
从文档中可以看出: 计算的属性被缓存,并且仅在反应性依赖项更改时重新计算。 然而下面的 fiddle 显示了一些不同的东西。
从 fiddle 如果您将标志设置为 2,如果您更改 myOtherValue
,计算的 属性 将被重新计算并执行,但是如果标志设置为 1。我认为它会跟踪您的 if 条件。
在文档中通常可以找到相关源代码的链接。 这是计算属性的代码:
我将只解决具体问题 vue.js 如何知道哪些依赖项影响哪些计算 属性?
简单的答案是,每次 vue 评估一个计算 属性 时,它都会创建一个映射,其中包含在该调用范围内访问的所有响应式属性。下次这些反应性属性中的任何一个发生变化时,它们将触发对计算 属性 的重新评估。
如果在计算的 属性 的最近评估期间,它的一个反应性依赖项从未达到(可能是因为它在 if/else 构造的非行进路径内),随后对该反应 属性 的更改不会触发对计算的 属性.
的重新评估通过修改此 fiddle 中的两个反应属性来观察此行为(只需在相应的输入框中键入)。需要注意的几点:
called
计算 属性 在文档加载时计算一次(它被触发是因为它在模板中呈现)。- 因为
path
设置为1
,将映射为依赖项的反应式 属性 是val1
。因此,它将是唯一可以在called
发生变化时触发重新评估的对象。val2
的值也可以更改,但不会对called
产生相同的影响,即使它明确存在于函数中。 - 当您单击 "Change Path" 按钮时,
path
从1
切换到2
。 - 在路径切换之后,请注意对
val1
的更改只会再次影响called
。由于path
在上次重新评估之前已设置为2
,因此val1
将无法访问,并且将不再映射为called
的依赖项。此后对其值的后续更改不会触发called
的重新计算。但是val2
现在已被映射为called
的依赖项,并且对它的更改会触发重新评估,就像之前对val1
所做的一样。直到下一个路径从2
切换回1
。
这是代码。
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
}
}
})
和相应的模板
<div id="app">
<input v-model="val1"/> {{val1}}
<br>
<input v-model="val2"/> {{val2}}
<br>
<button @click="changePath">change path</button>
<br>
{{ called }}
</div>