Vue.js - 如何正确监视嵌套数据

IT技术 javascript vue.js vue-component vue-resource
2021-01-31 04:01:05

我试图了解如何正确观察一些props变化。我有一个父组件(.vue 文件),它从 ajax 调用接收数据,将数据放入一个对象中,并使用它通过 v-for 指令呈现一些子组件,下面是我的实现的简化:

<template>
    <div>
        <player v-for="(item, key, index) in players"
            :item="item"
            :index="index"
            :key="key"">
        </player>
    </div>
</template>

...然后在<script>标签内:

 data(){
     return {
         players: {}
 },
 created(){
        let self = this;
        this.$http.get('../serv/config/player.php').then((response) => {
            let pls = response.body;
            for (let p in pls) {
                self.$set(self.players, p, pls[p]);
            }
    });
}

项目对象是这样的:

item:{
   prop: value,
   someOtherProp: {
       nestedProp: nestedValue,
       myArray: [{type: "a", num: 1},{type: "b" num: 6} ...]
    },
}

现在,在我的子“播放器”组件中,我试图观察任何 Item 的属性变化,我使用:

...
watch:{
    'item.someOtherProp'(newVal){
        //to work with changes in "myArray"
    },
    'item.prop'(newVal){
        //to work with changes in prop
    }
}

它有效,但对我来说似乎有点棘手,我想知道这是否是正确的方法。我的目标是每次prop更改或myArray获取新元素或现有元素中的某些变化时执行一些操作任何建议将不胜感激。

6个回答

您可以为此使用深度观察器:

watch: {
  item: {
     handler(val){
       // do stuff
     },
     deep: true
  }
}

这现在将检测item数组中对象的任何更改以及对数组本身的添加(与Vue.set 一起使用时)。这是一个 JSFiddle:http : //jsfiddle.net/je2rw3rs/

编辑

如果您不想监视顶级对象上的每个更改,并且只想使用一种不那么笨拙的语法来直接监视嵌套对象,则可以简单地观察一个computed

var vm = new Vue({
  el: '#app',
  computed: {
    foo() {
      return this.item.foo;
    }
  },
  watch: {
    foo() {
      console.log('Foo Changed!');
    }
  },
  data: {
    item: {
      foo: 'foo'
    }
  }
})

这是 JSFiddle:http : //jsfiddle.net/oa07r5fw/

对于深度观察者,观察者接受 args newValue, oldValue,但对于对象,我发现它传递了相同的值,两个 args。(可能是为了性能——他们不想对结构进行深层复制。)这意味着您无法判断为什么基于 args 调用处理程序。(如果这对你来说是个问题。)
2021-04-11 04:01:05

另一种比较优雅的好方法如下:

 watch:{
     'item.someOtherProp': function (newVal, oldVal){
         //to work with changes in someOtherProp
     },
     'item.prop': function(newVal, oldVal){
         //to work with changes in prop
     }
 }

(我在此处评论中从 @peerbolte 那里学到了这种方法

我正在观看的属性没有反应,我转向它并且它起作用了!
2021-03-21 04:01:05
+1 对于此解决方案,请记住您也可以使用此语法: 'item.someOtherProp'(newVal, oldVal){ .. }
2021-03-26 04:01:05
官方文档现在包括这个方法
2021-03-27 04:01:05
第一次看火,为什么?@feihcsim
2021-04-10 04:01:05

VueJs 深入观察子对象

new Vue({
    el: "#myElement",
    data: {
        entity: {
            properties: []
        }
    },
    watch: {
        'entity.properties': {
            handler: function (after, before) {
                // Changes detected. Do work...     
            },
            deep: true
        }
    }
});

如果您想观看一段时间的财产然后不观看它,该怎么办?

或者观看库子组件属性?

您可以使用“动态观察器”:

this.$watch(
 'object.property', //what you want to watch
 (newVal, oldVal) => {
    //execute your code here
 }
)

$watch返回的取消监视功能,这将驻足观望,如果它被调用。

var unwatch = vm.$watch('a', cb)
// later, teardown the watcher
unwatch()

您也可以使用该deep选项:

this.$watch(
'someObject', () => {
    //execute your code here
},
{ deep: true }
)

请务必查看文档

根据docs,您不应该使用箭头函数来定义观察者:Note that you should not use an arrow function to define a watcher (e.g. searchQuery: newValue => this.updateAutocomplete(newValue)). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.updateAutocomplete will be undefined.
2021-04-12 04:01:05

另一种添加我用来“破解”此解决方案的方法是这样做:我设置了一个单独的computed值,该值将简单地返回嵌套的对象值。

data : function(){
    return {
        countries : {
            UnitedStates : {
                value: "hello world";
            }.
        },
    };
},
computed : {
    helperName : function(){
        return this.countries.UnitedStates.value;
    },
},
watch : {
    helperName : function(newVal, oldVal){
        // do this...
    }
}
我只需要观察对象中的一个嵌套数据,所以这对我来说是正确的答案。谢谢
2021-04-04 04:01:05