How to Solve VUE Error: Avoid mutating a prop directly since the value will be overwritten …

1. Demand and error reporting

Requirements: the scenarios are: component a refers to component B, uses V-model to pass parameters to B, B uses props: {value} to receive content, directly modifies and assigns value according to logic in B, and sees error report in browser console after event triggering, as follows:

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. 
Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"

2. Analyze the reasons

In terms of the content of the error report, we have changed the variables of the parent component referenced in the child component, that is, the data in props; From the prompt information, is it feasible to use mutated ?In vue2, the data in the component props can only flow in one direction, that is, it can only pass props from the parent component through the component’s DOM attribute to the child component, and the child component can only passively receive the data from the parent component, and in the child component, the props data from the parent component cannot be modified. The value of props cannot be modified in the component, and the modified value will not be synchronized to the outer layer of the component, that is, the calling component does not know what the current state is inside the component

2.1 what causes this?

In the vue1. X version, the props binding modifiers twoway and . Sync can be used to realize the bidirectional data binding of props . Remove the bidirectional data binding function of props in vue2.0 . If bidirectional binding is needed, you need to implement it yourself
in vue2.0 , the data flow of component’s props is changed to only one-way flow, that is, it can only be transferred from (parent component) to (child component) through component’s v-bind: attributes , and the child component can only passively receive the data from the parent component, The props data passed by the parent component cannot be modified in the child component. Official document explanation:

Prop is unidirectional: when the properties of the parent component change, it is passed to the child component, but not vice versa. This is to prevent the child component from unintentionally modifying the state of the parent component – which makes the data flow of the application difficult to understand
although abandoning the two-way binding of props is beneficial and correct for the whole project, we do need to modify the requirements of props from within the component at some times

In vue2.0 , the following methods can be used to realize the bidirectional binding mode of component attributes (not binding, but asynchronous modification)

The V-model instruction or . Sync modifier will transfer the method of modifying attributes to the subcomponent call through v-bind . The subcomponent can directly use the method to transfer the method of modifying attributes to the subcomponent call through v-on , and use $emit() to implement callback modification or use this. $parent to modify

3. Solution: use v-on to realize the modification mode

It’s also for code readability

do not directly modify the props data passed from the parent component, redefine a variable in the data function, assign the props data value to the data variable, and then modify the data variable. As follows:

Component B accepts the parameters of component A

name: "B",
props: {
	father: {
		type: String,
		default: null
	}
}
data(){
  return{
    father_a : this.father
  }
}

If you want to listen to the variables passed in the a component to modify a data in the b component, you can use the watch listening function to listen. As follows:

name: "B",
props: {
	father: {
		type: String,
		default: null
	}
}
data(){
  return{
    father_a: this.father
    son: ''
  }
}
//Listening function, whenever the father variable passed from the parent component changes,
// the son variable defined in the child component will be assigned the value "son"
watch:{
  father(val, valOld){
    this.son = "Son"
  }
}

If b wants to modify the attributes passed by a , you can use $emit to modify the attributes

A

<B :father="a" @change="changeA" />

<script>
export default {
	name: 'A',
	data() {
		return {
			a: 'Variables of A'
		}
	},
	methods: {
		changeA(val) {
			this.a = val
		}
	}
}
</script>

B

<script>
export default {
	name: 'B',
	props: {
		father: {
			type: String,
			default: null
		}
	},
	data() {
	},
	watch:{
	  father(val, valOld){  // Here you can also define the variable in data and assign the father to it, and monitor the variable here
	    // This is the logic that the child component needs to handle if the father variable changes
	  }
	}, the
	methods: {
		changeAFather() { // Who calls it? It's the child component's business operation
			this.$emit('change', val)
		}
	}
}
</script>

So far, the data in the child component and the data in the parent component are bound Bi directionally, and the data inside and outside the component are synchronized: when the internal component changes, the external component decides whether to change

vue1.0 data bidirectional binding is abandoned in vue2.0 version?Through the case, it can also be found that there are many bidirectional binding props codes, which is not conducive to the data state management between components, especially in complex business. It is not easy to understand and read the logic, so we try not to use this way of bidirectional binding, and use vuex for data management in too complex data processing.


Read More: