返回

Vue 响应式编程谜团:computedAsync 的默认值陷阱

vue.js

Vue 响应式编程和 VueUse computedAsync:谜团破解

简介

在 Vue 的世界里,响应式编程和 computedAsync 是强大的工具,可以让我们的应用程序保持高效和灵活。然而,有时我们会遇到一些神秘的问题,使我们的代码无法按预期工作。本文将深入探讨在 Vue SFC 沙盒中使用 computedAsync 时,一个奇怪的谜团,并揭开其背后的原因和解决方法。

问题:storeData 保持为 -1

想象一下,我们有一个 Vue 组件,它使用 computedAsync 来从远程服务器获取数据。数据存储在一个名为 storeData 的计算属性中,而另一个名为 localData 的 ref 则存储本地数据。

然而,我们遇到了一个奇怪的问题:storeData 始终保持为 -1,而 localData 却可以正常更新。起初,这似乎是一个谜,但深入调查后,我们发现了一个巧妙的解决方案。

根源:computedAsync 和默认值

computedAsync 创建一个延迟的计算属性,这意味着它将在计算完成后的某个时间点返回一个值。在我们的案例中,computedAsync 设置了 3 秒的延迟,这意味着 storeData 在初始渲染时是空的。

这导致了问题,因为在 computedAsync 完成之前,storeData 无法更新。而 localData,作为一个 ref,可以在初始化时立即设置一个默认值,因此它可以正常工作。

解决方案:添加 watch 函数

为了解决这个问题,我们需要确保 storeData 在初始渲染时具有一个值。一种方法是添加一个 watch 函数,在 storeData 发生变化时执行一个回调函数。这将触发 computedStoreData 重新计算,从而导致 storeData 更新。

watch(storeData, () => {})

修复后的代码

<template>
  <p>{{ storeData }}</p>
  <p>{{ computedStoreData }}</p>
  <p>{{ localData }}</p>
  <p>{{ computedLocalData }}</p>
</template>

<script>
import { computed, watch, ref, computedAsync } from 'vue';
import { timeout } from 'promise-timeout';

const getTestData = computed(() => {
  if (! (venueId in _testDatas)) {
    _testDatas[venueId] = computedAsync(async () => {
      await timeout(3000);
      return venueId;
    }, -1, { lazy: false, default: 0 });
  }
  return unref(_testDatas[venueId]);
});

const storeData = computed(() => getTestData.value);
const computedStoreData = computed(() => storeData.value);

const localData = ref(-1);
const computedLocalData = computed(() => localData.value);

watch(storeData, () => {});
</script>

总结

通过仔细检查代码并添加 watch 函数,我们能够解决 storeData 无法更新的问题。这凸显了理解 Vue 响应式编程和 computedAsync 行为的重要性,以便构建健壮的 Vue 应用程序。

常见问题解答

1. 什么是 computedAsync?

computedAsync 是 VueUse 提供的一个计算属性,它允许我们创建一个延迟的计算属性,其值在计算完成后才可用。

2. computedAsync 的默认值是什么?

默认情况下,computedAsync 没有默认值,这意味着在计算完成之前,它将返回 undefined。我们可以通过使用 { default: value } 选项来指定一个默认值。

3. 为什么 watch 函数可以解决问题?

watch 函数允许我们在一个值发生变化时执行一个回调函数。在我们的案例中,我们使用 watch 函数来触发 computedStoreData 重新计算,从而更新 storeData。

4. 我应该始终为 computedAsync 指定一个默认值吗?

这取决于你的具体场景。如果你希望 computedAsync 在计算完成前返回一个值,那么指定一个默认值是明智的。

5. 还有什么其他方法可以解决这个问题?

除了使用 watch 函数,还可以通过使用 computed 的 getter 和 setter 函数来实现类似的行为。