Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should we use v-model to modify Vuex store?

Hello I am beginner in Vue and I do have a problem that's really bugging me. I am wondering should we use v-model directive to modify vuex store? Vuex says that we should modify vuex store only by mutations but v-model makes everything easier and shorter.(I am asking because i couldn't find clear answer)

like image 690
Krzysztof Kaczyński Avatar asked Feb 28 '19 14:02

Krzysztof Kaczyński


People also ask

What is the use of V-model in Vue?

Basic Usage You can use the v-model directive to create two-way data bindings on form input, textarea, and select elements. It automatically picks the correct way to update the element based on the input type.

How do you mutate Vuex state?

Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations.

Which part of Vuex is responsible for directly making changes to the data store?

The second key defined in the store is the mutations key. As the name suggests, it contain an object of all of the properties responsible for making changes to the state .

What does V-model lazy do?

lazy. By default, v-model syncs with the state of the Vue instance (data properties) on every input event - which means every single time the value of our input changes. The . lazy modifier changes our v-model so it only syncs after change events.


3 Answers

https://vuex.vuejs.org/guide/forms.html

When using Vuex in strict mode, it could be a bit tricky to use v-model on a piece of state that belongs to Vuex.

The "Vuex way" to deal with it is binding the <input>'s value and call an action on the input or change event.

Be sure to check out the simple "Two-way Computed Property" example on that page:

<input v-model="message">

computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}
like image 67
ceejayoz Avatar answered Oct 09 '22 12:10

ceejayoz


I think another good option which hasn't been mentioned in any answer here is to use vuex-map-fields. In fact, the library author has written a very nice explanation for the library's usefulness. As per its GitHub page, to use the library you can do something like this:

In your Vuex Store, you can have a snippet similar to this:

import Vue from 'vue';
import Vuex from 'vuex';

import { getField, updateField } from 'vuex-map-fields';

Vue.use(Vuex);

export default new Vuex.Store({
  // ...
  modules: {
    fooModule: {
      namespaced: true,
      state: {
        foo: '',
      },
      getters: {
        getField,
      },
      mutations: {
        updateField,
      },
    },
  },
});

And in your component code, you can have something along the lines of this:

<template>
  <div id="app">
    <input v-model="foo">
  </div>
</template>

<script>
import { mapFields } from 'vuex-map-fields';

export default {
  computed: {
    // `fooModule` is the name of the Vuex module.
    ...mapFields('fooModule', ['foo']),
  },
};
</script>

Additional examples for various use cases are shown in the library's GitHub repository that I linked to in the first sentence of this answer.

like image 24
Raj Avatar answered Oct 09 '22 14:10

Raj


Above solution can also implemented with mutations:

<template>
  <input v-model="message">
</template>

<script>
import { mapMutations, mapState } from 'vuex';

export default {
  computed: {
    ...mapState({messageFromStore: 'message'}),
    message: {
      get() {
        return this.messageFromStore;
      },
      set(value) {
        this.updateMessage(value);
      }
    }
  },
  methods: {
    ...mapMutations('updateMessage')
  }
};
</script>
like image 6
Simon Thiel Avatar answered Oct 09 '22 13:10

Simon Thiel