我有一个非常特殊的用例,我需要触发computed()
重新评估。据我所知,一旦内部使用的反应变量的状态发生变化,就会自动触发重新计算。
我的问题:这是唯一的情况吗?
考虑以下代码片段,其中返回当前(计算时)日期。该值设置一次后不会更改。我需要定期重新评估价值。
以下示例中循环例程在内部 computed()
运行,不会更改计算值:
- 重新评估空函数
<script setup lang="ts">
import { computed } from 'vue'
const counter = computed(() => {
setInterval(() => {}, 1000)
return new Date()
})
</script>
<template>
<h1>{{counter}}</h1>
</template>
- 重新计算标准变量
<script setup lang="ts">
import { computed } from 'vue'
const counter = computed(() => {
let u = 0
setInterval(() => {u++; console.log(u)}, 1000)
return new Date()
})
</script>
<template>
<h1>{{counter}}</h1>
</template>
- 重新计算反应变量
<script setup lang="ts">
import { computed, ref } from 'vue'
const counter = computed(() => {
const u = ref(0)
setInterval(() => {u.value++}, 1000)
return new Date()
})
</script>
<template>
<h1>{{counter}}</h1>
</template>
当反应变量在函数外部更改时,会发生重新计算:
<script setup lang="ts">
import { computed, ref } from 'vue'
const u = ref(0)
const counter = computed(() => {
u.value;
return new Date()
})
setInterval(() => {u.value++; console.log(u.value)}, 1000)
</script>
<template>
<h1>{{counter}}</h1>
</template>
我的问题(更准确地说):有没有办法setInterval()
在compute()函数内部运行?或者换句话说:到底是什么触发了重新计算?
setInterval()
注意:我知道这是一个奇怪的情况,我可以根据某个函数在 a 内部重新计算一个反应变量。除了这样对我来说更容易做到这一点之外,这对我来说也是一个了解反应周期细节的机会。
正如文档中所解释的,为了触发计算属性的反应性,需要在计算函数内部(同步)访问反应性数据,这样就可以跟踪它的更改。这发生在最后一个片段的情况下,
u.value
在计算函数的主体中读取。无法在 JavaScript 的其他代码片段中实现反应性,框架无法跟踪setInterval
回调内的更改并将它们与counter
.顾名思义,计算属性的目的是根据其他反应数据计算属性。最后一个片段是可行的,但误用了计算,因为
new Data
计算所依赖的反应数据不是从反应数据派生的(u
)。对于计算来说,包含副作用通常是一种不好的做法。异步副作用对于计算的工作方式来说是无用的,并会导致更多潜在的问题,在这种情况下setInterval
没有正确清理,可能会导致不良行为和内存泄漏。在极少数情况下,可以忽略此规则,例如翻译功能的实现,其中区域设置的更改应该重新计算本地化值:
计算是一种更简洁、更有效的方式来完成观察者所做的事情。只要一个案例不适合计算的常规用法,这意味着这是一个观察者的案例,这适用于所有涉及副作用的案例。在这种情况下,使用观察者编写的正确方法是:
在这种情况下,观察者是多余的,因为可以通过以下方式实现相同的结果: