[Vuejs]-Vue – Change computed property value without changing parent property value

2πŸ‘

βœ…

I know this already has an accepted answer, but I personally think adding a function as a prop should be an anti-pattern. It will work, but it rubs me the wrong way.

You were on the right path before. According to the Vue documentation, there are two instances when it will be tempting to mutate a prop

There are usually two cases where it’s tempting to mutate a prop:

  • The prop is used to pass in an initial value; the child component
    wants to use it as a local data property afterwards. In this case,
    it’s best to define a local data property that uses the prop as its
    initial value:
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
  • The prop is passed in as a raw value that needs to be transformed. In
    this case, it’s best to define a computed property using the prop’s
    value:
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

I think you are better off using your earlier method. Passing a function as props is a bit messy, in my opinion.

EDIT β€” this article confirms my hunch regarding passing functions as props. It is a bad idea. The article offers alternatives. I suggest you give it a read.

πŸ‘€Tony

1πŸ‘

When using computed properties you have 2 inner methods, get and set, but in this case your computed property reflects from props, so if you rerender the parent component it will be set back to the parent value, in this case "0".

You can send a method from the parent to change the value using props.

<template>
    <ChildComponent  :save="save" :isSaved="isSaved"/>
</template>

<script>

export default {
   name: "ParentComponent"
   data() {
      return {
         isSaved: false
      }
   }
    methods: {
       save() {
          this.isSaved = true;
       }
    }
};
</script>

You just need to set the save prop as function in the child component and call it.

<template>
    <button
        type="button"
        :style="{
           backgroundColor: isSaved ? 'gray' : '#68AEFA',
      }"
        @click="save()"
    >{{ isSaved ? 'Unsave' : 'Save' }}</button>
</template>

<script>

export default {
   name: "ChildComponent",
   data() {
      return {
         saved: false
      }
   }
   computed: {
      uniqueSaveStatus: {
         get() {
            return this.saved
         },
         set(v) {
            this.saved = v
         }
      }
   }
   props: {
      isSaved: Boolean,
      save: { type: Function }
   }
};
</script>

So if you really need the isSaved variable to be unique, you need to define it in the childComponent like uniqueSaveStatus.

Leave a comment