Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js - How to properly watch for nested data

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 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 <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 some variation inside existing ones. Any suggestion will be appreciated.

like image 381
Plastic Avatar asked Feb 09 '17 10:02

Plastic


People also ask

How do I watch data changes on Vue instance?

Using watchers in Vue # vue file we can watch for changes in data or props by using watch . For example, the below code will watch for a change in the data element pageData , and run a function according to the value it is changed to.

How do I watch an array in Vue?

You need to set deep to true when watching an array or object so that Vue knows that it should watch the nested data for changes. Join 11,067 other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.

How do you use a Vue watcher?

A watcher in Vue is a special feature that allows us to observe some data and perform specific actions when it changes. It is a more generic way to observe and react to data changes in the Vue instance.

What is the difference between watchers and computed property in VueJS?

Computed props can react to changes in multiple props, whereas watched props can only watch one at a time. Computed props are cached, so they only recalculate when things change. Watched props are executed every time. Computed props are evaluated lazily, meaning they are only executed when they are needed to be used.


2 Answers

You can use a deep watcher for that:

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

This will now detect any changes to the objects in the item array and additions to the array itself (when used with Vue.set). Here's a JSFiddle: http://jsfiddle.net/je2rw3rs/

EDIT

If you don't want to watch for every change on the top level object, and just want a less awkward syntax for watching nested objects directly, you can simply watch a computed instead:

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

Here's the JSFiddle: http://jsfiddle.net/oa07r5fw/

like image 61
craig_h Avatar answered Sep 28 '22 18:09

craig_h


Another good approach and one that is a bit more elegant is as follows:

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

(I learned this approach from @peerbolte in the comment here)

like image 42
RonC Avatar answered Sep 28 '22 16:09

RonC