Vue.js - How to properly watch for nested data

ghz 8months ago ⋅ 97 views

I'm trying to understand how to properly watch for some prop variation. I have a parent component (.vue files) that receive data from an ajax call, put the data inside an object and use it to render some child component through a v-for directive, below is a simplification of my implementation:

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

... then inside the <script> tag:

 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 objects are like this:

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

Now, inside my child "player" component I'm trying to watch for any item's property variation and I use:

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

It works but it seems a bit tricky to me and I was wondering if this is the right way to do it. My goal is to perform some action every time prop changes or myArray gets new elements or there is some variation inside existing ones. Any suggestions will be appreciated.

Answers

Your approach using watchers to monitor changes to specific properties of the item object in your child component is valid and should work correctly. However, if you want to watch for changes to nested properties within item.someOtherProp, you'll need to use deep watchers or traverse the nested properties manually.

Here are some suggestions and alternatives you can consider:

  1. Using Deep Watchers: Vue.js allows you to watch for changes to nested properties using deep watchers. You can specify a deep: true option in your watcher configuration to enable deep watching. This will automatically watch for changes to nested properties as well.

    watch: {
      'item.someOtherProp': {
        handler(newVal) {
          // Handle changes to item.someOtherProp
        },
        deep: true
      }
    }
    

    With this approach, changes to nested properties within item.someOtherProp will trigger the watcher.

  2. Using Computed Properties: Instead of using watchers, you can use computed properties to derive reactive data based on changes to the item object or its nested properties. Computed properties automatically update when their dependencies change.

    computed: {
      prop() {
        return this.item.prop;
      },
      myArray() {
        return this.item.someOtherProp.myArray;
      }
    }
    

    You can then perform your actions based on these computed properties.

  3. Manual Deep Observation: If deep watchers or computed properties don't suit your needs, you can manually traverse the nested properties and set up watchers for each level of nesting. This approach gives you more control but may be more verbose.

    watch: {
      'item.someOtherProp.myArray': {
        handler(newVal) {
          // Handle changes to item.someOtherProp.myArray
        },
        deep: true
      }
    }
    

    This approach can be useful if you only need to watch specific nested properties and not the entire object.

Choose the approach that best fits your requirements and coding style. Each method has its advantages and disadvantages, so consider factors such as readability, performance, and ease of maintenance when making your decision.