我在最初为空的地图周围有一个反应性:const map =reactive({});
,以及一个计算,它告诉如果地图有一个键“key”:const mapContainsKeyCompulated = Computed(() => map.hasOwnProperty("key"))
。当我更改地图时,计算结果不会更新。
我在这个问题上坚持了一天,并设法想出了一个演示该问题的最小示例:
<script setup> import {computed, reactive, ref, watch} from "vue"; const map = reactive({}); const key = "key"; const mapContainsKeyComputed = computed(() => map.hasOwnProperty(key)) const mapContainsKeyWatched = ref(map.hasOwnProperty(key)); watch(map, () => mapContainsKeyWatched.value = map.hasOwnProperty(key)) </script> <template> Map: {{map}} <br/> Computed: does map contain "key"? {{mapContainsKeyComputed}} <br/> Watch: does map contain key? {{mapContainsKeyWatched}} <br/> <button @click="map[key] = 'value'">add key-value</button> </template>
我已经阅读了一堆 stackoverflow 答案和 Vue 文档,但我仍然无法弄清楚。
Map:{{map}}
(第14行)更新得很好?编辑:正如 @estus-flask 提到的,这是 3.2.46 中修复的 VueJS 错误。
Vue 反应性需要显式支持反应式对象方法。
hasOwnProperty
是相当低级的,因此它已经有一段时间不受支持了。如果没有支持,map.hasOwnProperty(key)
会尝试访问非反应性原始对象上的key
,并且不会触发反应性,因此第一个计算 调用不会设置可以在下一次
map
更改时触发的侦听器。解决此问题的一种方法是首先定义
key
(如另一个答案中所建议的),这是使反应性在 Vue 2 和 3 中工作的传统方法:另一种方法是访问响应式对象上缺少的
key
属性:另一种方法是使用
in
运算符。由于 Vue 3 使用Proxy
进行响应,因此可以通过has
trap 检测到属性被访问:对
hasOwnProperty
的支持已最近在 3.2.46 中添加,因此问题中的代码应该可以在最新的 Vue 版本中使用。map
并不是真正的地图。如果使用Map
,这在任何 Vue 3 版本中都会有所不同,Vue 支持它,并且预计map.has(key)
将触发反应性。