【问题标题】:Watching nested object in Vue using deep使用 deep 观察 Vue 中的嵌套对象
【发布时间】:2020-06-14 21:00:01
【问题描述】:

我正在尝试使用深度调用监视具有多个属性的数据对象,我需要知道在监视调用中触发了对象中的哪个属性更改。有没有办法知道处理程序中的属性。

data(){
   return {
        user:{
           first_name:'',
           last_name:'',
            }
    }
},
watch:{
    user:{
       deep:true,
       handler(value){
       //Here I want to know which property(first_name/last_name) change of the user object has triggered this.
        }
    }
}

【问题讨论】:

  • 可能需要迭代对象并比较前后的值。
  • @ChrisLi 那会很乏味,如果数据对象很大,我想知道Vue js是否有任何方法提供了要知道的属性。
  • 你也可以通过编程方式为每个键设置观察者,我不知道vue是否为此提供了方法。
  • @ChrisLi 当我尝试比较深度手表中的新旧值时,我发现两个对象属性都已更新为最新值,你对此有什么想法吗?
  • 可能是因为它们引用了同一个对象,这是我找到的解决方法github.com/vuejs/vue/issues/2164#issuecomment-432872718

标签: javascript vue.js


【解决方案1】:

vue 似乎没有办法确定哪些属性发生了变化。

使用您的示例在任何属性更改时触发监视回调。

但是vue还有一个选择:

// keypath
vm.$watch('a.b.c', function (newVal, oldVal) {
  // do something
})

https://vuejs.org/v2/api/#vm-watch

你的情况可能是这样的:

data(){
   return {
        user:{
           first_name:'',
           last_name:'',
            }
    }
},
watch:{
    "user.first_name": function(newVal, oldVal) {
      // todo
    },
    "user.last_name": function(newVal, oldVal) {
      // todo
    }
}

但我不确定这是不是好方法

更新来自 vue 文档

注意:当改变(而不是替换)对象或数组时, 旧值将与新值相同,因为它们引用 相同的对象/数组。 Vue 不保留预突变值的副本。

在这种情况下,手动比较对象是没有用的,因为 newVal = oldVal(一个引用)

upd2:重新创建一个对象可能会变通

// for example
user = Object.assign({}, user, { first_name: "newValOfFirstName" })

// instead of
user.first_name = "newValOfFirstName";

【讨论】:

  • @Gurmaks 感谢您的回答,我想在单个处理程序中处理整个对象更改,尽管我尝试比较对象,但似乎 Vue 正在传递具有最新值的旧对象和新对象,所以也无法比较,这是 Vue 中的错误还是我做错了什么。
  • 我忘记了,抱歉。来自 vue 文档“注意:当改变(而不是替换)对象或数组时,旧值将与新值相同,因为它们引用相同的对象/数组。Vue 不保留预变异的副本价值。”。这意味着在这种情况下手动比较是没有用的,因为 newVal = oldVal。这是一个对象。我会更新我的答案
  • 或者你可以重新创建对象,而不是变异
【解决方案2】:

你可以这样做:

<template>
  <div>
    <div>
      <input type="text" v-model="obj.prop1" />
      <input type="text" v-model="obj.prop2" />
      <input type="text" v-model="obj.prop3" />
    </div>
  </div>
</template>

<script>
export default {
  name: 'app',
  data: () => ({
    obj: {
      prop1: '',
      prop2: '',
      prop3: '',
    },
  }),
  mounted() {
    for (const key in this.obj) {
      this.$watch(
        () => this.obj[key],
        (newValue, oldValue) => {
          console.log(key, oldValue, newValue);
        }
      );
    }
  },
};
</script>

使用this.$watch 方法可以创建动态观察者。

更多详情可以查看文档:https://vuejs.org/v2/api/#watch

【讨论】:

  • 这个答案解决了你的问题吗?请接受此答案,这将对其他人有所帮助。
猜你喜欢
  • 2015-07-19
  • 2022-11-25
  • 2020-08-28
  • 2021-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多