Vue Compute() 未在反应式地图上触发
P粉127901279
P粉127901279 2024-03-27 10:36:32
0
1
372

我在最初为空的地图周围有一个反应性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 文档,但我仍然无法弄清楚。

  • 为什么 mapContainsKeyCompulated 没有更新?
  • 如果反应式不“跟踪”向地图添加或删除键,为什么Map:{{map}}(第14行)更新得很好?
  • 当我用 array[] 替换 map{} 并将“hasOwnProperty”替换为“includes()”时,它工作正常。有什么不同?
  • 如何解决这个问题,而不需要使用丑陋的“watch”解决方案(其中“map.hasOwnProperty(key)”必须重复)?

编辑:正如 @estus-flask 提到的,这是 3.2.46 中修复的 VueJS 错误。

P粉127901279
P粉127901279

全部回复(1)
P粉668146636

Vue 反应性需要显式支持反应式对象方法。 hasOwnProperty 是相当低级的,因此它已经有一段时间不受支持了。如果没有支持,map.hasOwnProperty(key) 会尝试访问非反应性原始对象上的key,并且不会触发反应性,因此第一个计算 调用不会设置可以在下一次 map 更改时触发的侦听器。

解决此问题的一种方法是首先定义 key (如另一个答案中所建议的),这是使反应性在 Vue 2 和 3 中工作的传统方法:

const map = reactive({ key: undefined })

另一种方法是访问响应式对象上缺少的 key 属性:

const mapContainsKeyComputed = computed(() => map[key] !== undefined)

另一种方法是使用 in 运算符。由于 Vue 3 使用 Proxy 进行响应,因此可以通过 has trap 检测到属性被访问:

const mapContainsKeyComputed = computed(() => key in map)

hasOwnProperty 的支持已最近在 3.2.46 中添加,因此问题中的代码应该可以在最新的 Vue 版本中使用。

map 并不是真正的地图。如果使用 Map,这在任何 Vue 3 版本中都会有所不同,Vue 支持它,并且预计 map.has(key) 将触发反应性。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板