我在试着理解如何正确地观察一些道具的变化。 我有一个父组件(。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对象是这样的:

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

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

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

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


当前回答

https://vuejs.org/guide/essentials/watchers.html#deep-watchers

export default {
  watch: {
    someObject: {
      handler(newValue, oldValue) {
        // Note: `newValue` will be equal to `oldValue` here
        // on nested mutations as long as the object itself
        // hasn't been replaced.
      },
      deep: true
    }
  }
}

其他回答

https://vuejs.org/guide/essentials/watchers.html#deep-watchers

export default {
  watch: {
    someObject: {
      handler(newValue, oldValue) {
        // Note: `newValue` will be equal to `oldValue` here
        // on nested mutations as long as the object itself
        // hasn't been replaced.
      },
      deep: true
    }
  }
}

跟踪列表中单个更改的项

如果你想监视列表中的所有项目,并知道列表中的哪个项目发生了变化,你可以在每个项目上分别设置自定义监视器,如下所示:

var vm = new Vue({
  data: {
    list: [
      {name: 'obj1 to watch'},
      {name: 'obj2 to watch'},
    ],
  },
  methods: {
    handleChange (newVal, oldVal) {
      // Handle changes here!
      // NOTE: For mutated objects, newVal and oldVal will be identical.
      console.log(newVal);
    },
  },
  created () {
    this.list.forEach((val) => {
      this.$watch(() => val, this.handleChange, {deep: true});
    });
  },
});

如果你的列表没有立即填充(就像在最初的问题中),你可以将逻辑从created移到任何需要的地方,例如在.then()块中。

观察不断变化的列表

如果你的列表本身更新到有新的或删除的项目,我已经开发了一个有用的模式,“浅层”观察列表本身,并动态观察/取消观察项目随着列表的变化:

// NOTE: This example uses Lodash (_.differenceBy and _.pull) to compare lists
//       and remove list items. The same result could be achieved with lots of
//       list.indexOf(...) if you need to avoid external libraries.

var vm = new Vue({
  data: {
    list: [
      {name: 'obj1 to watch'},
      {name: 'obj2 to watch'},
    ],
    watchTracker: [],
  },
  methods: {
    handleChange (newVal, oldVal) {
      // Handle changes here!
      console.log(newVal);
    },
    updateWatchers () {
      // Helper function for comparing list items to the "watchTracker".
      const getItem = (val) => val.item || val;

      // Items that aren't already watched: watch and add to watched list.
      _.differenceBy(this.list, this.watchTracker, getItem).forEach((item) => {
        const unwatch = this.$watch(() => item, this.handleChange, {deep: true});
        this.watchTracker.push({ item: item, unwatch: unwatch });
        // Uncomment below if adding a new item to the list should count as a "change".
        // this.handleChange(item);
      });

      // Items that no longer exist: unwatch and remove from the watched list.
      _.differenceBy(this.watchTracker, this.list, getItem).forEach((watchObj) => {
        watchObj.unwatch();
        _.pull(this.watchTracker, watchObj);
        // Optionally add any further cleanup in here for when items are removed.
      });
    },
  },
  watch: {
    list () {
      return this.updateWatchers();
    },
  },
  created () {
    return this.updateWatchers();
  },
});

如果你想看一段时间的财产,然后取消它怎么办? 或者查看库子组件属性?

你可以使用“动态观察者”:

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

$watch返回一个unwatch函数,如果被调用,它将停止监视。

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

你也可以使用deep选项:

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

请一定要看一下医生

另一种更好的方法是:

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

(我从评论里的@peerbolte那里学到了这个方法)

另一种补充方法是,我曾经“破解”这个解决方案是这样做的: 我设置了一个单独的计算值,它将简单地返回嵌套的对象值。

data : function(){
    return {
        countries : {
            UnitedStates : {
                value: "hello world";
            }.
        },
    };
},
computed : {
    helperName : function(){
        return this.countries.UnitedStates.value;
    },
},
watch : {
    helperName : function(newVal, oldVal){
        // do this...
    }
}