[Vuejs]-Watch for the whole array as well as one of the properties of it

0👍

You can mark the non-reactive properties as non-configurable, and Vue will not detect changes in their values.

let arr = [{id:1, name:"first"}, {id:2, name:"second"}];

arr.forEach(item => Object.defineProperty(item, "id", {configurable: false}));

Alternatively, you could use a shallow watcher and require code that modifies the reactive properties to use Vue.set() instead of simple assignment.

Vue.set(arr[0], "name", "new name");  // don't use arr[0].name = "new name";

0👍

You can create a child component, where you bind objects to the array and place the watcher inside the child component as below:

Parent.vue

<template>
  <child-component v-for="point in points" :point="point"  ></child-component>
</template>
data: {
return {
  points: [{id:1, name:"first"}, {id:2, name:"second"}] 
}
}

Child.vue:

props: ['point']
...
watch: {
  name: function(newVal){
    // watch name field
  }
}

0👍

One way would be to create a computed property that just touches the bits you care about and then watch that instead.

new Vue({
  el: '#app',
  
  data () {
    return {
      points: [{id: 1, name: 'first'}, {id: 2, name: 'second'}]
    }
  },
    
  computed: {
    pointStuffICareAbout () {
      return this.points.map(point => point.name)
    }
  },  
    
  methods: {
    updateId () {
      this.points[0].id = Math.round(Math.random() * 1000)
    },
    
    updateName () {
      this.points[0].name = Math.random().toString(36).slice(2, 7)
    },
    
    addItem () {
      this.points.push({id: 3, name: 'third'})
    }
  },
  
  watch: {
    pointStuffICareAbout () {
      console.log('watcher triggered')
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <button @click="updateId">Update id</button>
  <button @click="updateName">Update name</button>
  <button @click="addItem">Add item</button>
  <p>
    {{ points }}
  </p>
</div>

Leave a comment