Tenho um caso de uso muito específico em que preciso acionar uma computed()
reavaliação. Pelo que eu sei, a recomputação é acionada automaticamente quando o estado de uma variável reativa usada internamente muda.
Minha pergunta: este é o único caso?
Considere os seguintes trechos de código onde a data atual (no momento da computação) é retornada. O valor é definido uma vez e não muda. Preciso que o valor seja reavaliado regularmente.
Os exemplos a seguir, onde uma rotina cíclica está sendo executada internamente computed()
, não alteram o valor calculado:
- uma função vazia é reavaliada
<script setup lang="ts">
import { computed } from 'vue'
const counter = computed(() => {
setInterval(() => {}, 1000)
return new Date()
})
</script>
<template>
<h1>{{counter}}</h1>
</template>
- uma variável padrão é recalculada
<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>
- uma variável reativa é recalculada
<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>
Quando uma variável reativa é alterada fora da função, o recálculo acontece:
<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>
Minha pergunta (mais precisamente): existe uma maneira de executar setInterval()
a função computada()? Ou em outras palavras: o que exatamente desencadeia uma recomputação?
Nota: eu sei que este é um caso estranho e que eu poderia ter uma variável reativa recalculada dentro de a setInterval()
com base em alguma função. Além de ser mais fácil fazer dessa forma, é uma oportunidade para aprender detalhes sobre o ciclo de reatividade.
Conforme explicado na documentação , para que a reatividade de uma propriedade computada seja acionada, os dados reativos precisam ser acessados (de forma síncrona) dentro da função computada, o que permite que eles sejam rastreados em busca de alterações. Isso acontece no caso do último trecho,
u.value
ser lido no corpo da função computada. Não há como a reatividade ser implementada em outros trechos em JavaScript, uma estrutura não poderia rastrear as alterações dentrosetInterval
do retorno de chamada e associá-las aocounter
.O objetivo da propriedade computada é calcular uma propriedade a partir de outros dados reativos, como o nome sugere. O último trecho é viável, mas faz mau uso de um cálculo, porque
new Data
não deriva de dados reativos dos quais o cálculo depende (u
). Geralmente é uma prática ruim que um computador contenha efeitos colaterais . Os efeitos colaterais assíncronos são inúteis para o funcionamento de um computador e causam mais problemas potenciais; neste caso,setInterval
não são limpos adequadamente e podem resultar em comportamento indesejado e vazamentos de memória.Em casos raros, esta regra pode ser ignorada, por exemplo, a implementação da função de tradução onde a mudança em uma localidade deve recalcular o valor localizado:
Um computador é uma maneira mais concisa e eficiente de fazer o que um observador faz. Desde que um caso não se enquadre no uso regular de um computador, isso significa que este é um caso para um observador, e isso se aplica a todos os casos que envolvem efeitos colaterais. Neste caso, uma maneira adequada de escrever com um observador seria:
Neste caso, um observador é redundante, pois o mesmo resultado poderia ser alcançado com: