为什么 Vue3 中的空对象不是响应式的?

Nec*_*hoj 5 javascript vue.js vue-reactivity vuejs3

当我从空对象创建 aref并随后添加对象属性时,没有反应性:

<template>
  <p>{{hello}}</p>
  <button @click="add()">Click me</button>
</template>

<script>
import {ref} from 'vue';
export default {
  name: "Test",
  setup(){
    const myData = ref({});
    return {myData}
  },
  methods: {
    add(){
      this.myData["text"] = "Hello";
      console.log(this.myData);
    }
  },
  computed: {
    hello(){
      return this.myData.hasOwnProperty("text")) ? this.myData["text"] : "no text";
    }
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

单击按钮显示myData 已更改,但计算的属性hello未更新。

也尝试过reactive({})而不是ref({})没有成功。

当我们使用诸如 之类的属性初始化 ref 时,它会起作用const myData = ref({"text": "no text"});

但为什么空对象不起作用呢?

编辑:
终于找到了问题到底是什么以及如何解决:Vue3 的反应性核心不警惕属性的Object.keys()值,而仅警惕属性的值,而空对象没有任何属性值。但是,如果计算属性定义如下,则可以使 Vue3 发出警报

computed: {
    hello(){
      return Object.keys(this.myData).indexOf("text") > -1 ? this.myData["text"] : "no text";
    }
Run Code Online (Sandbox Code Playgroud)

需要调用 来Object.keys(this.myData)让反应系统知道我们感兴趣的内容。这类似于设置watchonObject.keys(this.myData)而不是 watch this.myData

Nik*_*vic 2

尝试更新您的 ref 对象,例如

this.myData = {"text": "Hello"}
Run Code Online (Sandbox Code Playgroud)

this.myData = {"text": "Hello"}
Run Code Online (Sandbox Code Playgroud)
const { ref, computed } = Vue
const app = Vue.createApp({
  /*setup(){
    const myData = ref({});
    const hello = computed(() => myData.value.hasOwnProperty("text") ? myData.value.text : myData.value = "no text")
    const add = () => {
      if(Object.keys(myData.value).length === 0) {
        myData.value = {'text': "Hello"};
      } else {
        myData.value.otherProperty = "Hello again"
      }
    }
    return { myData, add, hello }
  },*/
  setup(){
    const myData = ref({});
    return { myData }
  },
  methods: {
    add(){
      if(Object.keys(this.myData).length === 0) {
        this.myData = {"text": "Hello"}
      } else {
        this.myData.otherProperty = "Hello again"
      }
      console.log(this.myData)
    },
  },
  computed: {
    hello(){
      return Object.keys(this.myData).length !== 0 ? this.myData[Object.keys(this.myData)[Object.keys(this.myData).length - 1]] : "no text"
    }
  }
})
app.mount('#demo')
Run Code Online (Sandbox Code Playgroud)