Form Fields, Two-Way Data Binding and Vuex

One of the most valuable features that Vue.js has to offer, is painless two-way data binding. By using the v-model
directive, you can quickly set up two-way data binding on form elements.

  



export default {
  data() {
    // Changing the value of `message` here
    // or changing the value of the `input`
    // directly, updates the value in both
    // places.
    return { message: '' },
  },
};

So far so good. But as our application is growing, we might want to use a more powerful, but also a more complex state management pattern like Vuex. One of the core principles of state management patterns like Vuex is immutability: we’re not allowed to change the state in a Vuex store directly, but we have to use so called “mutations” to trigger state changes.

Vuex form handling

Let’s take our first example and modify it to use a Vuex store for state management.

  



export default {
  data() {
    return {
      // Attention: this is the
      // wrong way of doing this!
      form: this.$store.state.form,
    };
  },
};

To make this work we need to set up a new Vuex store instance.

// ...

export default new Vuex.Store({
  strict: true,
  state: {
    form: { message: '' },
  },
});

If we check this out in the browser, it works – kinda. Although updating the value of the input field directly will update the value in the store and updating the value in the store will update the text in the input, if we take a look at the browser console, we can see, that this is not the correct way of implementing this.

Error: [vuex] Do not mutate vuex store state outside mutation handlers.

Because we’ve initialized the Vuex store in strict mode (which you should definitely do in your development environment), we get an error message telling us that it is not allowed to mutate the Vuex store outside of a mutation handler.

Correct ways of handling form data with Vuex

If we take a look at the chapter about form handling in the official Vuex documentation
we can read about two recommended ways of how to handle form data with Vuex.

Although both recommendations are pretty straightforward as long as you’re dealing with just a few form fields, they quickly become cumbersome when dealing with a lot of form fields.

  
  
  
  



export default {
  computed: {
    firstName: {
      get() {
        return this.$store.state.form.firstName;
      },
      set(value) {
        this.$store.commit('updateFirstName', value);
      },
    },
    lastName: {
      get() {
        return this.$store.state.form.lastName;
      },
      set(value) {
        this.$store.commit('updateLastName', value);
      },
    },
    message: {
      get() {
        return this.$store.state.form.message;
      },
      set(value) {
        this.$store.commit('updateMessage', value);
      },
    },
    // ...
  },
};

As you can see in the example above, although the officially recommended way of using two-way computed properties is pretty straightforward and works perfectly fine, it becomes tedious to handle more than a few form fields this way. If we take a closer look, we can see there is a lot of repetition in this code. Where there’s repetition, there’s potential to do some refactoring / abstraction.

Using vuex-map-fields for simple Vuex form handling

After fiddling around with some code to come up with a reusable implementation of the two-way computed property approach, I decided to create a new npm package for handling Vuex powered form fields: vuex-map-fields
.

With vuex-map-fields
we can take the code from above and refactor it.

  
  
  
  



import { mapFields } from 'vuex-map-fields';

export default {
  computed: {
    ...mapFields([
      'form.firstName',
      'form.lastName',
      'form.message',
      // ...
    ]),
  },
};

vuex-map-fields
also provides the mutation and getter functions needed to retrieve and mutate data.

// ...

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

export default new Vuex.Store({
  strict: true,
  state: {
    form: {
      firstName: '',
      lastName: '',
      message: '',
      // ...
    },
  },
  getters: {
    getField,
  },
  mutations: {
    updateField,
  },
});

vuex-map-fields
is taking care of creating the necessary getter and setter functions for the two-way computed properties. The updateField()
mutation in the store takes care of mutating the corresponding field value when the field is updated.

Final thoughts

I was really surprised to learn that there is no convenient way, how to handle form field data with Vuex. Usually with Vue we’re used to an amazing “out of the box experience” but not so much with handling two-way data binding on form fields in combination with Vuex.

vuex-map-fields
can help with dealing with this problem and doing so without having a very large footprint – the file size of vuex-map-fields
is just about 690 bytes (gziped).

I hope this article and the vuex-map-fields
package are helpful for some people.

您可能感兴趣的

Authentication Best Practices for Vue Vue authentication management Introduction Whenever you start to get serious with a project, you will most likely face the issues of how to handle...
大型Vuex应用程序的目录结构 译者按:听前端大佬聊聊Vuex大型项目架构的经验 原文: Large-scale Vuex application structures 译者:Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。 在...
How to Build Complex, Large-Scale Vue.js Apps With... It's so easy to learn and use Vue.js that anyone can build a simple application with that framework. Even novices, with the help of Vue's document...
@MrTung约稿–Vuex 的数据持久化 本篇文章的诞生是因为@MrTung留言说想让我介绍一下vue数据持久化相关内容,每一位订阅专栏的用户都是我的客户,而客户的要求是必须满足的。如果你有想了解的内容,欢迎你给我留言。 1.Vuex 数据持久化问题的原因 我们都知道Vuex的state数据都是存储在内存中的,如果用户刷新页...
web前端vue:vuex单独一文件使用方式 上次我用了一个加减的例子为大家讲解vuex的基本的使用方式,和在什么样的情况下使用。上次还是在一个组件内把这个例子简单的展示了下,这次我把vuex抽离出来一个单独的文件,统一管理整个项目的状态。 上次也说了如果你的项目够大,那用vuex来管理整个项目的状态,那是再好不过的,如果是小项目的话就...
责编内容来自:Markus Oberlehner (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » Form Fields, Two-Way Data Binding and Vuex



专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录