The vue.js docs are quite strict in saying that mutating props inside of the component is bad practice. Also there are two cases described, in which a developer may be tempted to break this rule:
Since I started with vue.js I found myself tempted updating a props property using v-model
. Seaching the web I found several discussions which included workarounds or use vuex.
My question is: Is updating a property of a prop using v-model
OK or is BAD because it alters parent state.
Imo I want to alter the parent state, consider this example
A Crud component, that loads a specific "form" component:
<template>
<awesome-form @formSubmit="onFormSubmit" :entity="entity"></awesome-form>
</template>
<script>
import AwesomeForm from 'SomeForm'
export default {
data () {
return {
entity: {}
}
},
components: {
AwesomeForm
},
methods: {
onFormSubmit () {
axios.post('/backend', this.entity)
}
}
}
</script>
The specific form component:
<template>
<form @submit.prevent="submit">
<input type="text" name="username" v-model="entity.username" />
...
</form>
</template>
<script>
export default {
props: {
entity: {
type: Object
}
},
methods: {
submit () {
this.$emit('formSubmit')
}
}
}
</script>
This works like intended and makes data binding super easy. But I guess this is considered bad, as it updates parent state. But in the end of the day this is exactly what i want.
Is this really bad and what are the alternatives?
I see that the best practice in your case is using .sync
modifier as mentioned in official docs
:
// ignore the following two lines, they just disable warnings in "Run code snippet"
Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('awesome-form', {
props: ['entity'],
template: `
<div>
<form @submit.prevent="submit">
<input type="text" class="form-control" name="username" v-model="entity.username">
<input type="email" class="form-control" name="email" v-model="entity.email">
<input type="submit" class="btn btn-primary" value="submit"/>
</form>
</div>`,
methods: {
submit() {
this.$emit('form-submit')
}
}
})
new Vue({
el: "#app",
data() {
return {
entity: {
username: '',
email: ''
}
}
},
methods: {
onFormSubmit() {
console.log(this.entity)
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<div id="app">
<awesome-form @form-submit="onFormSubmit" :entity.sync="entity"></awesome-form>
<p> {{entity}}</p>
</div>