Home > Software design >  Cannot watch a cloned value
Cannot watch a cloned value

Time:01-20

Here is minimal example of my problem. I tried to find a similar question on SO but didn't found anything, so sorry if it's a duplicate.

App.vue

 <template>
  <div>
    <SubComponent v-model="myValue" />
    <SubComponent v-model="myClonedValue" />
  </div>
</template>

<script>
import SubComponent from "./components/SubComponent";

export default {
  components: { SubComponent },
  data: function () {
    return {
      myValue: {
        foo: 45,
        bar: 38,
      },
    };
  },
  computed: {
    myClonedValue: function () {
      return { ...this.myValue };
    },
  },
  watch: {
    "myValue.foo": function (val, oldVal) {
      console.log(val, oldVal);
    },
    /* This Doesn't work either

    "myClonedValue.foo": function (val, oldVal) {
      console.log(val, oldVal);
    },
    */
    myClonedValue: {
      handler: function (val, oldVal) {
        console.log(val, oldVal);
      },
      deep: true,
    },
  },
};
</script>

SubComponent

<template>
  <input v-model="value.foo" type="text" />
</template>

<script>
export default {
  name: "SubComponent",
  props: {
    msg: String,
    value: Object,
  },
};
</script>

Problem

In my main use case, I've a object that I want to modify only if the changes are confirmed. So I clone its values with computed property and for some reason I need to watch if some values have been modified. My problem here, as you can see it online on this CodeSandBox CodeSandBox project Is that VueJS doesn't detect any change once I clone the data value. If you change the second input of my example, nothing happens.

How can I solve this ?

CodePudding user response:

Computed property doesn't just clone the original value once. It creates a reactive binding and recomputes every time the original value changes. So you need a different approach.

Make clonedValue a regular data property and assign a value to it in created or mounted lifecycle hook. Then you will be able to watch it just as your original value. And what (i assume) is more important, now you will be able to modify the original and cloned values independently.

data: {
    myValue: { foo: 1, bar: 2 },
    clonedValue: {}
},
created() {
    this.clonedValue = {...this.myValue}
}

CodePudding user response:

You can use deep watchers to achieve that, but you may have to check the inner keys yourself

watch: {
    myValue: {
        handler (val, oldVal) {
            if(val.prop !== oldVal.prop){
               // do something
            }
        },
        deep: true,
    },
},
  •  Tags:  
  • Related