Typically, when you’re building a Vue component and make use of the v-model directive on a component, you’re working with state that is meant to be local to that component. You might be computing other properties based off that property or you might even be watching for changes to perform some action local to that component. But it’s not terribly common to store that intermediate state in a central store (Vuex). The solution to this use case is obvious once you see it but first, I want to cover the two options that might come to mind but aren’t the best available.
One hacky option would be to continue using local state and link it to the store via watchers.
<input v-model="myInput">
computed: {
storedInput () {
return this.$store.state.myInput
}
},
watchers: {
storedInput (newValue) {
this.myInput = newValue
},
myInput (newValue) {
this.$store.commit('setMyInput', newValue)
}
},
A better but still verbose solution to the problem would be to replicate the v-model behavior with v-bind:value and listening to events first on the element. This way you can create your own update code without using watchers.
<input :value="myInput" @input="updateMyInput">
computed: {
myInput () {
return this.$store.state.myInput
}
},
methods: {
updateMyInput (e) {
this.$store.commit('setMyInput', e.target.value)
}
}
Finally, the best option (something I missed on my first run through the Vuex docs) is the suggestion to use Vue’s two-way computed properties in this scenario. Of course! This option is less verbose but more importantly plugs into the reactivity of Vue much more nicely.
<input v-model="myInput">
computed: {
myInput: {
get () {
return this.$store.state.myInput
},
set (newValue) {
this.$store.commit('setMyInput', newValue)
}
}
}