Vue 响应式编程谜团:computedAsync 的默认值陷阱
2024-03-25 03:50:39
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 函数来实现类似的行为。