vue.jsvuejs2getset

Vue computed methods can't change data using setter in template


I need change data using computed:

<template>
    <div>{{ userDataTest }}</div>
</template>

props: {
    exampleData: {
        type: Object,
        required: true,
    },
},

computed: {
    userDataTest: {
        get: function() {
            return this.exampleData;
        },
        set: function(newValue) {
            console.log(newValue);
            return newValue;
        },
    },
}

mounted () {
    setTimeout(() => {
        console.log('Change now to null!');
        this.userDataTest = null;
    }, 5000);
},

I get data using props, next I create computed methods with getter and setter. I added userDataTest in <template>. And the I change (using mounted) data in this.userDataTest to null using setter. In console.log(newValue); in setter I see newValue is null, but in <template> nothing change still I have data from getter.

Why setter not change data in <template> to null ?


Solution

  • Mutating a prop locally is considered an anti-pattern

    However, you can use the .sync modifier as shown below, but you can't set the prop to null because you are specifying that it has to be an Object type.

    Vue.component('my-component', {
      template: `<div>{{ userDataTest }}</div>`,
      props: {
        exampleData: {
          type: Object,
          required: true
        }
      },
    
      computed: {
        userDataTest: {
          get: function() {
            return this.exampleData
          },
          set: function(newValue) {
            this.$emit('update:exampleData', newValue)
          }
        }
      },
    
      mounted() {
        setTimeout(() => {
          console.log('Change now!')
          this.userDataTest = {}
        }, 2500)
      }
    })
    
    new Vue({
      el: '#app',
    
      data() {
        return {
          exampleData: {
            foo: 'bar'
          }
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
    
    <div id="app">
      <my-component :example-data.sync="exampleData"></my-component>
    </div>